diff --git a/Documentation/ABI/testing/sysfs-devices-power_resources_D0 b/Documentation/ABI/testing/sysfs-devices-power_resources_D0 new file mode 100644 index 0000000000000000000000000000000000000000..73b77a6be19654e38849d25a0d9a0b1bffb7574f --- /dev/null +++ b/Documentation/ABI/testing/sysfs-devices-power_resources_D0 @@ -0,0 +1,13 @@ +What: /sys/devices/.../power_resources_D0/ +Date: January 2013 +Contact: Rafael J. Wysocki +Description: + The /sys/devices/.../power_resources_D0/ directory is only + present for device objects representing ACPI device nodes that + use ACPI power resources for power management. + + If present, it contains symbolic links to device directories + representing ACPI power resources that need to be turned on for + the given device node to be in ACPI power state D0. The names + of the links are the same as the names of the directories they + point to. diff --git a/Documentation/ABI/testing/sysfs-devices-power_resources_D1 b/Documentation/ABI/testing/sysfs-devices-power_resources_D1 new file mode 100644 index 0000000000000000000000000000000000000000..30c20703fb8cfb90530a7baa4c94e6c42f77ba93 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-devices-power_resources_D1 @@ -0,0 +1,14 @@ +What: /sys/devices/.../power_resources_D1/ +Date: January 2013 +Contact: Rafael J. Wysocki +Description: + The /sys/devices/.../power_resources_D1/ directory is only + present for device objects representing ACPI device nodes that + use ACPI power resources for power management and support ACPI + power state D1. + + If present, it contains symbolic links to device directories + representing ACPI power resources that need to be turned on for + the given device node to be in ACPI power state D1. The names + of the links are the same as the names of the directories they + point to. diff --git a/Documentation/ABI/testing/sysfs-devices-power_resources_D2 b/Documentation/ABI/testing/sysfs-devices-power_resources_D2 new file mode 100644 index 0000000000000000000000000000000000000000..fd9d84b421e1c663f578de44cc123586acdde8fa --- /dev/null +++ b/Documentation/ABI/testing/sysfs-devices-power_resources_D2 @@ -0,0 +1,14 @@ +What: /sys/devices/.../power_resources_D2/ +Date: January 2013 +Contact: Rafael J. Wysocki +Description: + The /sys/devices/.../power_resources_D2/ directory is only + present for device objects representing ACPI device nodes that + use ACPI power resources for power management and support ACPI + power state D2. + + If present, it contains symbolic links to device directories + representing ACPI power resources that need to be turned on for + the given device node to be in ACPI power state D2. The names + of the links are the same as the names of the directories they + point to. diff --git a/Documentation/ABI/testing/sysfs-devices-power_resources_D3hot b/Documentation/ABI/testing/sysfs-devices-power_resources_D3hot new file mode 100644 index 0000000000000000000000000000000000000000..3df32c20addf5b5c3e0abcdb6411e7bdc6e8e18c --- /dev/null +++ b/Documentation/ABI/testing/sysfs-devices-power_resources_D3hot @@ -0,0 +1,14 @@ +What: /sys/devices/.../power_resources_D3hot/ +Date: January 2013 +Contact: Rafael J. Wysocki +Description: + The /sys/devices/.../power_resources_D3hot/ directory is only + present for device objects representing ACPI device nodes that + use ACPI power resources for power management and support ACPI + power state D3hot. + + If present, it contains symbolic links to device directories + representing ACPI power resources that need to be turned on for + the given device node to be in ACPI power state D3hot. The + names of the links are the same as the names of the directories + they point to. diff --git a/Documentation/ABI/testing/sysfs-devices-power_state b/Documentation/ABI/testing/sysfs-devices-power_state new file mode 100644 index 0000000000000000000000000000000000000000..7ad9546748f012f2526a5479e3e7e28f1d658682 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-devices-power_state @@ -0,0 +1,20 @@ +What: /sys/devices/.../power_state +Date: January 2013 +Contact: Rafael J. Wysocki +Description: + The /sys/devices/.../power_state attribute is only present for + device objects representing ACPI device nodes that provide power + management methods. + + If present, it contains a string representing the current ACPI + power state of the given device node. Its possible values, + "D0", "D1", "D2", "D3hot", and "D3cold", reflect the power state + names defined by the ACPI specification (ACPI 4 and above). + + If the device node uses shared ACPI power resources, this state + determines a list of power resources required not to be turned + off. However, some power resources needed by the device node in + higher-power (lower-number) states may also be ON because of + some other devices using them at the moment. + + This attribute is read-only. diff --git a/Documentation/ABI/testing/sysfs-devices-real_power_state b/Documentation/ABI/testing/sysfs-devices-real_power_state new file mode 100644 index 0000000000000000000000000000000000000000..8b3527c82a7d00c5113a7f1aa91a1bac5f813a0e --- /dev/null +++ b/Documentation/ABI/testing/sysfs-devices-real_power_state @@ -0,0 +1,23 @@ +What: /sys/devices/.../real_power_state +Date: January 2013 +Contact: Rafael J. Wysocki +Description: + The /sys/devices/.../real_power_state attribute is only present + for device objects representing ACPI device nodes that provide + power management methods and use ACPI power resources for power + management. + + If present, it contains a string representing the real ACPI + power state of the given device node as returned by the _PSC + control method or inferred from the configuration of power + resources. Its possible values, "D0", "D1", "D2", "D3hot", and + "D3cold", reflect the power state names defined by the ACPI + specification (ACPI 4 and above). + + In some situations the value of this attribute may be different + from the value of the /sys/devices/.../power_state attribute for + the same device object. If that happens, some shared power + resources used by the device node are only ON because of some + other devices using them at the moment. + + This attribute is read-only. diff --git a/Documentation/ABI/testing/sysfs-devices-resource_in_use b/Documentation/ABI/testing/sysfs-devices-resource_in_use new file mode 100644 index 0000000000000000000000000000000000000000..b4a3bc5922a3094295158fe282e64c7158496f4e --- /dev/null +++ b/Documentation/ABI/testing/sysfs-devices-resource_in_use @@ -0,0 +1,12 @@ +What: /sys/devices/.../resource_in_use +Date: January 2013 +Contact: Rafael J. Wysocki +Description: + The /sys/devices/.../resource_in_use attribute is only present + for device objects representing ACPI power resources. + + If present, it contains a number (0 or 1) representing the + current status of the given power resource (0 means that the + resource is not in use and therefore it has been turned off). + + This attribute is read-only. diff --git a/Documentation/acpi/enumeration.txt b/Documentation/acpi/enumeration.txt index 54469bc81b1cbac644e482bd09ebb6c28b77db43..94a656131885f9bd7a2761c9a9b0e6853db54789 100644 --- a/Documentation/acpi/enumeration.txt +++ b/Documentation/acpi/enumeration.txt @@ -63,8 +63,8 @@ from ACPI tables. Currently the kernel is not able to automatically determine from which ACPI device it should make the corresponding platform device so we need to add the ACPI device explicitly to acpi_platform_device_ids list defined in -drivers/acpi/scan.c. This limitation is only for the platform devices, SPI -and I2C devices are created automatically as described below. +drivers/acpi/acpi_platform.c. This limitation is only for the platform +devices, SPI and I2C devices are created automatically as described below. SPI serial bus support ~~~~~~~~~~~~~~~~~~~~~~ diff --git a/Documentation/acpi/scan_handlers.txt b/Documentation/acpi/scan_handlers.txt new file mode 100644 index 0000000000000000000000000000000000000000..3246ccf159925026e99451a581246f38eff8fff4 --- /dev/null +++ b/Documentation/acpi/scan_handlers.txt @@ -0,0 +1,77 @@ +ACPI Scan Handlers + +Copyright (C) 2012, Intel Corporation +Author: Rafael J. Wysocki + +During system initialization and ACPI-based device hot-add, the ACPI namespace +is scanned in search of device objects that generally represent various pieces +of hardware. This causes a struct acpi_device object to be created and +registered with the driver core for every device object in the ACPI namespace +and the hierarchy of those struct acpi_device objects reflects the namespace +layout (i.e. parent device objects in the namespace are represented by parent +struct acpi_device objects and analogously for their children). Those struct +acpi_device objects are referred to as "device nodes" in what follows, but they +should not be confused with struct device_node objects used by the Device Trees +parsing code (although their role is analogous to the role of those objects). + +During ACPI-based device hot-remove device nodes representing pieces of hardware +being removed are unregistered and deleted. + +The core ACPI namespace scanning code in drivers/acpi/scan.c carries out basic +initialization of device nodes, such as retrieving common configuration +information from the device objects represented by them and populating them with +appropriate data, but some of them require additional handling after they have +been registered. For example, if the given device node represents a PCI host +bridge, its registration should cause the PCI bus under that bridge to be +enumerated and PCI devices on that bus to be registered with the driver core. +Similarly, if the device node represents a PCI interrupt link, it is necessary +to configure that link so that the kernel can use it. + +Those additional configuration tasks usually depend on the type of the hardware +component represented by the given device node which can be determined on the +basis of the device node's hardware ID (HID). They are performed by objects +called ACPI scan handlers represented by the following structure: + +struct acpi_scan_handler { + const struct acpi_device_id *ids; + struct list_head list_node; + int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id); + void (*detach)(struct acpi_device *dev); +}; + +where ids is the list of IDs of device nodes the given handler is supposed to +take care of, list_node is the hook to the global list of ACPI scan handlers +maintained by the ACPI core and the .attach() and .detach() callbacks are +executed, respectively, after registration of new device nodes and before +unregistration of device nodes the handler attached to previously. + +The namespace scanning function, acpi_bus_scan(), first registers all of the +device nodes in the given namespace scope with the driver core. Then, it tries +to match a scan handler against each of them using the ids arrays of the +available scan handlers. If a matching scan handler is found, its .attach() +callback is executed for the given device node. If that callback returns 1, +that means that the handler has claimed the device node and is now responsible +for carrying out any additional configuration tasks related to it. It also will +be responsible for preparing the device node for unregistration in that case. +The device node's handler field is then populated with the address of the scan +handler that has claimed it. + +If the .attach() callback returns 0, it means that the device node is not +interesting to the given scan handler and may be matched against the next scan +handler in the list. If it returns a (negative) error code, that means that +the namespace scan should be terminated due to a serious error. The error code +returned should then reflect the type of the error. + +The namespace trimming function, acpi_bus_trim(), first executes .detach() +callbacks from the scan handlers of all device nodes in the given namespace +scope (if they have scan handlers). Next, it unregisters all of the device +nodes in that scope. + +ACPI scan handlers can be added to the list maintained by the ACPI core with the +help of the acpi_scan_add_handler() function taking a pointer to the new scan +handler as an argument. The order in which scan handlers are added to the list +is the order in which they are matched against device nodes during namespace +scans. + +All scan handles must be added to the list before acpi_bus_scan() is run for the +first time and they cannot be removed from it. diff --git a/Documentation/cpu-freq/cpu-drivers.txt b/Documentation/cpu-freq/cpu-drivers.txt index c436096351f84ce15d13f02fe8f3148ea9940435..72f70b16d29984b1829b3998c611d4c9af524192 100644 --- a/Documentation/cpu-freq/cpu-drivers.txt +++ b/Documentation/cpu-freq/cpu-drivers.txt @@ -111,6 +111,12 @@ policy->governor must contain the "default policy" for For setting some of these values, the frequency table helpers might be helpful. See the section 2 for more information on them. +SMP systems normally have same clock source for a group of cpus. For these the +.init() would be called only once for the first online cpu. Here the .init() +routine must initialize policy->cpus with mask of all possible cpus (Online + +Offline) that share the clock. Then the core would copy this mask onto +policy->related_cpus and will reset policy->cpus to carry only online cpus. + 1.3 verify ------------ diff --git a/Documentation/cpu-freq/user-guide.txt b/Documentation/cpu-freq/user-guide.txt index 04f6b32993e69ca4185a81bbaadb677aac5056e9..ff2f28332cc43b27c7b4fa787efe4d69aed76f0a 100644 --- a/Documentation/cpu-freq/user-guide.txt +++ b/Documentation/cpu-freq/user-guide.txt @@ -190,11 +190,11 @@ scaling_max_freq show the current "policy limits" (in first set scaling_max_freq, then scaling_min_freq. -affected_cpus : List of CPUs that require software coordination - of frequency. +affected_cpus : List of Online CPUs that require software + coordination of frequency. -related_cpus : List of CPUs that need some sort of frequency - coordination, whether software or hardware. +related_cpus : List of Online + Offline CPUs that need software + coordination of frequency. scaling_driver : Hardware driver for cpufreq. diff --git a/Documentation/devicetree/bindings/arm/kirkwood.txt b/Documentation/devicetree/bindings/arm/kirkwood.txt new file mode 100644 index 0000000000000000000000000000000000000000..98cce9a653ebfba870398c5936d91f0af39b3076 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/kirkwood.txt @@ -0,0 +1,27 @@ +Marvell Kirkwood Platforms Device Tree Bindings +----------------------------------------------- + +Boards with a SoC of the Marvell Kirkwood +shall have the following property: + +Required root node property: + +compatible: must contain "marvell,kirkwood"; + +In order to support the kirkwood cpufreq driver, there must be a node +cpus/cpu@0 with three clocks, "cpu_clk", "ddrclk" and "powersave", +where the "powersave" clock is a gating clock used to switch the CPU +between the "cpu_clk" and the "ddrclk". + +Example: + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "marvell,sheeva-88SV131"; + clocks = <&core_clk 1>, <&core_clk 3>, <&gate_clk 11>; + clock-names = "cpu_clk", "ddrclk", "powersave"; + }; diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 6c723811c0a09f3ad5b2b18fa32ef12aa55cd82a..4c5b3f993bbbf2eb60095b18537285e1ac7ffb14 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1039,16 +1039,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted. Claim all unknown PCI IDE storage controllers. idle= [X86] - Format: idle=poll, idle=mwait, idle=halt, idle=nomwait + Format: idle=poll, idle=halt, idle=nomwait Poll forces a polling idle loop that can slightly improve the performance of waking up a idle CPU, but will use a lot of power and make the system run hot. Not recommended. - idle=mwait: On systems which support MONITOR/MWAIT but - the kernel chose to not use it because it doesn't save - as much power as a normal idle loop, use the - MONITOR/MWAIT idle loop anyways. Performance should be - the same as idle=poll. idle=halt: Halt is forced to be used for CPU idle. In such case C2/C3 won't be used again. idle=nomwait: Disable mwait for CPU C-states @@ -1131,6 +1126,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted. 0 disables intel_idle and fall back on acpi_idle. 1 to 6 specify maximum depth of C-state. + intel_pstate= [X86] + disable + Do not enable intel_pstate as the default + scaling driver for the supported processors + intremap= [X86-64, Intel-IOMMU] on enable Interrupt Remapping (default) off disable Interrupt Remapping @@ -1886,10 +1886,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted. wfi(ARM) instruction doesn't work correctly and not to use it. This is also useful when using JTAG debugger. - no-hlt [BUGS=X86-32] Tells the kernel that the hlt - instruction doesn't work correctly and not to - use it. - no_file_caps Tells the kernel not to honor file capabilities. The only way then for a file to be executed with privilege is to be setuid root or executed by root. diff --git a/Documentation/power/freezing-of-tasks.txt b/Documentation/power/freezing-of-tasks.txt index 6ec291ea1c78c64e4e1ec35ad614336859ab4c31..85894d83b3525f2ff0bc6033b80d50ef220d906b 100644 --- a/Documentation/power/freezing-of-tasks.txt +++ b/Documentation/power/freezing-of-tasks.txt @@ -223,3 +223,8 @@ since they ask the freezer to skip freezing this task, since it is anyway only after the entire suspend/hibernation sequence is complete. So, to summarize, use [un]lock_system_sleep() instead of directly using mutex_[un]lock(&pm_mutex). That would prevent freezing failures. + +V. Miscellaneous +/sys/power/pm_freeze_timeout controls how long it will cost at most to freeze +all user space processes or all freezable kernel threads, in unit of millisecond. +The default value is 20000, with range of unsigned integer. diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt index 03591a750f99eea57fa63a5b610cf70793c716c6..6c9f5d9aa115d04ee86c5297f5e3051bee31c0b9 100644 --- a/Documentation/power/runtime_pm.txt +++ b/Documentation/power/runtime_pm.txt @@ -426,6 +426,10 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h: 'power.runtime_error' is set or 'power.disable_depth' is greater than zero) + bool pm_runtime_active(struct device *dev); + - return true if the device's runtime PM status is 'active' or its + 'power.disable_depth' field is not equal to zero, or false otherwise + bool pm_runtime_suspended(struct device *dev); - return true if the device's runtime PM status is 'suspended' and its 'power.disable_depth' field is equal to zero, or false otherwise diff --git a/Documentation/trace/events-power.txt b/Documentation/trace/events-power.txt index cf794af22855458ed06133d6acbcd372180730ae..e1498ff8cf94df2bf5a4e14fb93c04c94444e803 100644 --- a/Documentation/trace/events-power.txt +++ b/Documentation/trace/events-power.txt @@ -17,7 +17,7 @@ Cf. include/trace/events/power.h for the events definitions. 1. Power state switch events ============================ -1.1 New trace API +1.1 Trace API ----------------- A 'cpu' event class gathers the CPU-related events: cpuidle and @@ -41,31 +41,6 @@ The event which has 'state=4294967295' in the trace is very important to the use space tools which are using it to detect the end of the current state, and so to correctly draw the states diagrams and to calculate accurate statistics etc. -1.2 DEPRECATED trace API ------------------------- - -A new Kconfig option CONFIG_EVENT_POWER_TRACING_DEPRECATED with the default value of -'y' has been created. This allows the legacy trace power API to be used conjointly -with the new trace API. -The Kconfig option, the old trace API (in include/trace/events/power.h) and the -old trace points will disappear in a future release (namely 2.6.41). - -power_start "type=%lu state=%lu cpu_id=%lu" -power_frequency "type=%lu state=%lu cpu_id=%lu" -power_end "cpu_id=%lu" - -The 'type' parameter takes one of those macros: - . POWER_NONE = 0, - . POWER_CSTATE = 1, /* C-State */ - . POWER_PSTATE = 2, /* Frequency change or DVFS */ - -The 'state' parameter is set depending on the type: - . Target C-state for type=POWER_CSTATE, - . Target frequency for type=POWER_PSTATE, - -power_end is used to indicate the exit of a state, corresponding to the latest -power_start event. - 2. Clocks events ================ The clock events are used for clock enable/disable and for diff --git a/arch/arm/boot/dts/highbank.dts b/arch/arm/boot/dts/highbank.dts index 5927a8df562536550b101669f45978f33907e0ac..6aad34ad9517f37424071dcac4859c400a93d1f5 100644 --- a/arch/arm/boot/dts/highbank.dts +++ b/arch/arm/boot/dts/highbank.dts @@ -37,6 +37,16 @@ next-level-cache = <&L2>; clocks = <&a9pll>; clock-names = "cpu"; + operating-points = < + /* kHz ignored */ + 1300000 1000000 + 1200000 1000000 + 1100000 1000000 + 800000 1000000 + 400000 1000000 + 200000 1000000 + >; + clock-latency = <100000>; }; cpu@901 { diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index c6dec5fc20aa42440ce7267766f257449550550a..047d3e40e47062d4946d7f7c11e8330132340654 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -172,14 +172,9 @@ static void default_idle(void) local_irq_enable(); } -void (*pm_idle)(void) = default_idle; -EXPORT_SYMBOL(pm_idle); - /* - * The idle thread, has rather strange semantics for calling pm_idle, - * but this is what x86 does and we need to do the same, so that - * things like cpuidle get called in the same way. The only difference - * is that we always respect 'hlt_counter' to prevent low power idle. + * The idle thread. + * We always respect 'hlt_counter' to prevent low power idle. */ void cpu_idle(void) { @@ -210,10 +205,10 @@ void cpu_idle(void) } else if (!need_resched()) { stop_critical_timings(); if (cpuidle_idle_call()) - pm_idle(); + default_idle(); start_critical_timings(); /* - * pm_idle functions must always + * default_idle functions must always * return with IRQs enabled. */ WARN_ON(irqs_disabled()); diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c index 49f335d301bae4c8f381143de37f4afb42975dce..ae0c7bb39ae88b5b9bdbf17b6272f309742f9b47 100644 --- a/arch/arm/kernel/smp_twd.c +++ b/arch/arm/kernel/smp_twd.c @@ -31,7 +31,6 @@ static void __iomem *twd_base; static struct clk *twd_clk; static unsigned long twd_timer_rate; -static bool common_setup_called; static DEFINE_PER_CPU(bool, percpu_setup_called); static struct clock_event_device __percpu **twd_evt; @@ -239,25 +238,28 @@ static irqreturn_t twd_handler(int irq, void *dev_id) return IRQ_NONE; } -static struct clk *twd_get_clock(void) +static void twd_get_clock(struct device_node *np) { - struct clk *clk; int err; - clk = clk_get_sys("smp_twd", NULL); - if (IS_ERR(clk)) { - pr_err("smp_twd: clock not found: %d\n", (int)PTR_ERR(clk)); - return clk; + if (np) + twd_clk = of_clk_get(np, 0); + else + twd_clk = clk_get_sys("smp_twd", NULL); + + if (IS_ERR(twd_clk)) { + pr_err("smp_twd: clock not found %d\n", (int) PTR_ERR(twd_clk)); + return; } - err = clk_prepare_enable(clk); + err = clk_prepare_enable(twd_clk); if (err) { pr_err("smp_twd: clock failed to prepare+enable: %d\n", err); - clk_put(clk); - return ERR_PTR(err); + clk_put(twd_clk); + return; } - return clk; + twd_timer_rate = clk_get_rate(twd_clk); } /* @@ -280,26 +282,7 @@ static int __cpuinit twd_timer_setup(struct clock_event_device *clk) } per_cpu(percpu_setup_called, cpu) = true; - /* - * This stuff only need to be done once for the entire TWD cluster - * during the runtime of the system. - */ - if (!common_setup_called) { - twd_clk = twd_get_clock(); - - /* - * We use IS_ERR_OR_NULL() here, because if the clock stubs - * are active we will get a valid clk reference which is - * however NULL and will return the rate 0. In that case we - * need to calibrate the rate instead. - */ - if (!IS_ERR_OR_NULL(twd_clk)) - twd_timer_rate = clk_get_rate(twd_clk); - else - twd_calibrate_rate(); - - common_setup_called = true; - } + twd_calibrate_rate(); /* * The following is done once per CPU the first time .setup() is @@ -330,7 +313,7 @@ static struct local_timer_ops twd_lt_ops __cpuinitdata = { .stop = twd_timer_stop, }; -static int __init twd_local_timer_common_register(void) +static int __init twd_local_timer_common_register(struct device_node *np) { int err; @@ -350,6 +333,8 @@ static int __init twd_local_timer_common_register(void) if (err) goto out_irq; + twd_get_clock(np); + return 0; out_irq: @@ -373,7 +358,7 @@ int __init twd_local_timer_register(struct twd_local_timer *tlt) if (!twd_base) return -ENOMEM; - return twd_local_timer_common_register(); + return twd_local_timer_common_register(NULL); } #ifdef CONFIG_OF @@ -405,7 +390,7 @@ void __init twd_local_timer_of_register(void) goto out; } - err = twd_local_timer_common_register(); + err = twd_local_timer_common_register(np); out: WARN(err, "twd_local_timer_of_register failed (%d)\n", err); diff --git a/arch/arm/mach-davinci/cpuidle.c b/arch/arm/mach-davinci/cpuidle.c index 9107691adbdb73673abe7ed7f66c420190b33af8..5ac9e9384b1531c8e05e3adf7aec91f2171a9798 100644 --- a/arch/arm/mach-davinci/cpuidle.c +++ b/arch/arm/mach-davinci/cpuidle.c @@ -25,35 +25,44 @@ #define DAVINCI_CPUIDLE_MAX_STATES 2 -struct davinci_ops { - void (*enter) (u32 flags); - void (*exit) (u32 flags); - u32 flags; -}; +static DEFINE_PER_CPU(struct cpuidle_device, davinci_cpuidle_device); +static void __iomem *ddr2_reg_base; +static bool ddr2_pdown; + +static void davinci_save_ddr_power(int enter, bool pdown) +{ + u32 val; + + val = __raw_readl(ddr2_reg_base + DDR2_SDRCR_OFFSET); + + if (enter) { + if (pdown) + val |= DDR2_SRPD_BIT; + else + val &= ~DDR2_SRPD_BIT; + val |= DDR2_LPMODEN_BIT; + } else { + val &= ~(DDR2_SRPD_BIT | DDR2_LPMODEN_BIT); + } + + __raw_writel(val, ddr2_reg_base + DDR2_SDRCR_OFFSET); +} /* Actual code that puts the SoC in different idle states */ static int davinci_enter_idle(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) { - struct cpuidle_state_usage *state_usage = &dev->states_usage[index]; - struct davinci_ops *ops = cpuidle_get_statedata(state_usage); - - if (ops && ops->enter) - ops->enter(ops->flags); + davinci_save_ddr_power(1, ddr2_pdown); index = cpuidle_wrap_enter(dev, drv, index, arm_cpuidle_simple_enter); - if (ops && ops->exit) - ops->exit(ops->flags); + davinci_save_ddr_power(0, ddr2_pdown); return index; } -/* fields in davinci_ops.flags */ -#define DAVINCI_CPUIDLE_FLAGS_DDR2_PWDN BIT(0) - static struct cpuidle_driver davinci_idle_driver = { .name = "cpuidle-davinci", .owner = THIS_MODULE, @@ -70,45 +79,6 @@ static struct cpuidle_driver davinci_idle_driver = { .state_count = DAVINCI_CPUIDLE_MAX_STATES, }; -static DEFINE_PER_CPU(struct cpuidle_device, davinci_cpuidle_device); -static void __iomem *ddr2_reg_base; - -static void davinci_save_ddr_power(int enter, bool pdown) -{ - u32 val; - - val = __raw_readl(ddr2_reg_base + DDR2_SDRCR_OFFSET); - - if (enter) { - if (pdown) - val |= DDR2_SRPD_BIT; - else - val &= ~DDR2_SRPD_BIT; - val |= DDR2_LPMODEN_BIT; - } else { - val &= ~(DDR2_SRPD_BIT | DDR2_LPMODEN_BIT); - } - - __raw_writel(val, ddr2_reg_base + DDR2_SDRCR_OFFSET); -} - -static void davinci_c2state_enter(u32 flags) -{ - davinci_save_ddr_power(1, !!(flags & DAVINCI_CPUIDLE_FLAGS_DDR2_PWDN)); -} - -static void davinci_c2state_exit(u32 flags) -{ - davinci_save_ddr_power(0, !!(flags & DAVINCI_CPUIDLE_FLAGS_DDR2_PWDN)); -} - -static struct davinci_ops davinci_states[DAVINCI_CPUIDLE_MAX_STATES] = { - [1] = { - .enter = davinci_c2state_enter, - .exit = davinci_c2state_exit, - }, -}; - static int __init davinci_cpuidle_probe(struct platform_device *pdev) { int ret; @@ -124,11 +94,7 @@ static int __init davinci_cpuidle_probe(struct platform_device *pdev) ddr2_reg_base = pdata->ddr2_ctlr_base; - if (pdata->ddr2_pdown) - davinci_states[1].flags |= DAVINCI_CPUIDLE_FLAGS_DDR2_PWDN; - cpuidle_set_statedata(&device->states_usage[1], &davinci_states[1]); - - device->state_count = DAVINCI_CPUIDLE_MAX_STATES; + ddr2_pdown = pdata->ddr2_pdown; ret = cpuidle_register_driver(&davinci_idle_driver); if (ret) { diff --git a/arch/arm/mach-exynos/include/mach/cpufreq.h b/arch/arm/mach-exynos/include/mach/cpufreq.h index 7517c3f417af86cd62bf8ee54262d356586be9ad..b5d39dd03b2ae20fb96d135dd46b8b3597ae0021 100644 --- a/arch/arm/mach-exynos/include/mach/cpufreq.h +++ b/arch/arm/mach-exynos/include/mach/cpufreq.h @@ -18,12 +18,25 @@ enum cpufreq_level_index { L20, }; +#define APLL_FREQ(f, a0, a1, a2, a3, a4, a5, a6, a7, b0, b1, b2, m, p, s) \ + { \ + .freq = (f) * 1000, \ + .clk_div_cpu0 = ((a0) | (a1) << 4 | (a2) << 8 | (a3) << 12 | \ + (a4) << 16 | (a5) << 20 | (a6) << 24 | (a7) << 28), \ + .clk_div_cpu1 = (b0 << 0 | b1 << 4 | b2 << 8), \ + .mps = ((m) << 16 | (p) << 8 | (s)), \ + } + +struct apll_freq { + unsigned int freq; + u32 clk_div_cpu0; + u32 clk_div_cpu1; + u32 mps; +}; + struct exynos_dvfs_info { unsigned long mpll_freq_khz; unsigned int pll_safe_idx; - unsigned int pm_lock_idx; - unsigned int max_support_idx; - unsigned int min_support_idx; struct clk *cpu_clk; unsigned int *volt_table; struct cpufreq_frequency_table *freq_table; diff --git a/arch/arm/mach-highbank/Kconfig b/arch/arm/mach-highbank/Kconfig index 551c97e87a78bedf6bae2e2c4d7e5f93496088c8..44b12f9c1584a205f4b66f48fe426a3293a342cb 100644 --- a/arch/arm/mach-highbank/Kconfig +++ b/arch/arm/mach-highbank/Kconfig @@ -1,5 +1,7 @@ config ARCH_HIGHBANK bool "Calxeda ECX-1000/2000 (Highbank/Midway)" if ARCH_MULTI_V7 + select ARCH_HAS_CPUFREQ + select ARCH_HAS_OPP select ARCH_WANT_OPTIONAL_GPIOLIB select ARM_AMBA select ARM_GIC @@ -11,5 +13,7 @@ config ARCH_HIGHBANK select GENERIC_CLOCKEVENTS select HAVE_ARM_SCU select HAVE_SMP + select MAILBOX + select PL320_MBOX select SPARSE_IRQ select USE_OF diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index 7be3622cfc850711bea6f5b1385b7631ea7033dd..2d93d8b238351fa37fbc76405ba6e8382067afa2 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -351,12 +351,10 @@ static void omap3_pm_idle(void) if (omap_irq_pending()) goto out; - trace_power_start(POWER_CSTATE, 1, smp_processor_id()); trace_cpu_idle(1, smp_processor_id()); omap_sram_idle(); - trace_power_end(smp_processor_id()); trace_cpu_idle(PWR_EVENT_EXIT, smp_processor_id()); out: diff --git a/arch/arm/mach-tegra/cpu-tegra.c b/arch/arm/mach-tegra/cpu-tegra.c index a74d3c7d2e26836beac265f15db1c3c69b1575c7..a36a03d3c9a08f8af52d9ad4d679e494cfa7016b 100644 --- a/arch/arm/mach-tegra/cpu-tegra.c +++ b/arch/arm/mach-tegra/cpu-tegra.c @@ -243,8 +243,7 @@ static int tegra_cpu_init(struct cpufreq_policy *policy) /* FIXME: what's the actual transition time? */ policy->cpuinfo.transition_latency = 300 * 1000; - policy->shared_type = CPUFREQ_SHARED_TYPE_ALL; - cpumask_copy(policy->related_cpus, cpu_possible_mask); + cpumask_copy(policy->cpus, cpu_possible_mask); if (policy->cpu == 0) register_pm_notifier(&tegra_cpu_pm_notifier); diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c index cb0956bc96edfe15333b0aee0012a15dcb730d13..c7002d40a9b012313758ababf2908e4bf1ccde77 100644 --- a/arch/arm64/kernel/process.c +++ b/arch/arm64/kernel/process.c @@ -97,14 +97,9 @@ static void default_idle(void) local_irq_enable(); } -void (*pm_idle)(void) = default_idle; -EXPORT_SYMBOL_GPL(pm_idle); - /* - * The idle thread, has rather strange semantics for calling pm_idle, - * but this is what x86 does and we need to do the same, so that - * things like cpuidle get called in the same way. The only difference - * is that we always respect 'hlt_counter' to prevent low power idle. + * The idle thread. + * We always respect 'hlt_counter' to prevent low power idle. */ void cpu_idle(void) { @@ -122,10 +117,10 @@ void cpu_idle(void) local_irq_disable(); if (!need_resched()) { stop_critical_timings(); - pm_idle(); + default_idle(); start_critical_timings(); /* - * pm_idle functions should always return + * default_idle functions should always return * with IRQs enabled. */ WARN_ON(irqs_disabled()); diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c index 3e16ad9b0a99ab0615731f12bfffbf0195cf20d0..8061426b7df5a9269194e1471d2df4a98d260361 100644 --- a/arch/blackfin/kernel/process.c +++ b/arch/blackfin/kernel/process.c @@ -39,12 +39,6 @@ int nr_l1stack_tasks; void *l1_stack_base; unsigned long l1_stack_len; -/* - * Powermanagement idle function, if any.. - */ -void (*pm_idle)(void) = NULL; -EXPORT_SYMBOL(pm_idle); - void (*pm_power_off)(void) = NULL; EXPORT_SYMBOL(pm_power_off); @@ -81,7 +75,6 @@ void cpu_idle(void) { /* endless idle loop with no priority at all */ while (1) { - void (*idle)(void) = pm_idle; #ifdef CONFIG_HOTPLUG_CPU if (cpu_is_offline(smp_processor_id())) diff --git a/arch/cris/kernel/process.c b/arch/cris/kernel/process.c index 7f65be6f7f17741153222d11618a716593fbbb91..104ff4dd9b98dd1aa0c00177ae1e83d2f8138a54 100644 --- a/arch/cris/kernel/process.c +++ b/arch/cris/kernel/process.c @@ -54,11 +54,6 @@ void enable_hlt(void) EXPORT_SYMBOL(enable_hlt); -/* - * The following aren't currently used. - */ -void (*pm_idle)(void); - extern void default_idle(void); void (*pm_power_off)(void); @@ -77,16 +72,12 @@ void cpu_idle (void) while (1) { rcu_idle_enter(); while (!need_resched()) { - void (*idle)(void); /* * Mark this as an RCU critical section so that * synchronize_kernel() in the unload path waits * for our completion. */ - idle = pm_idle; - if (!idle) - idle = default_idle; - idle(); + default_idle(); } rcu_idle_exit(); schedule_preempt_disabled(); diff --git a/arch/ia64/hp/common/aml_nfw.c b/arch/ia64/hp/common/aml_nfw.c index 6192f7188654e0549c01d934e7073a68890c7f7a..916ffe770bcf5691c0e2b6744a40f0d45c81d487 100644 --- a/arch/ia64/hp/common/aml_nfw.c +++ b/arch/ia64/hp/common/aml_nfw.c @@ -191,7 +191,7 @@ static int aml_nfw_add(struct acpi_device *device) return aml_nfw_add_global_handler(); } -static int aml_nfw_remove(struct acpi_device *device, int type) +static int aml_nfw_remove(struct acpi_device *device) { return aml_nfw_remove_global_handler(); } diff --git a/arch/ia64/include/asm/acpi.h b/arch/ia64/include/asm/acpi.h index 359e68a03ca3e47ca1ea71df04b3fd04cba14e31..faa1bf0da8153ffd1a0a1ebbae690308b6a9c962 100644 --- a/arch/ia64/include/asm/acpi.h +++ b/arch/ia64/include/asm/acpi.h @@ -52,10 +52,6 @@ /* Asm macros */ -#define ACPI_ASM_MACROS -#define BREAKPOINT3 -#define ACPI_DISABLE_IRQS() local_irq_disable() -#define ACPI_ENABLE_IRQS() local_irq_enable() #define ACPI_FLUSH_CPU_CACHE() static inline int diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index 31360cbbd5f8951e7f816aba3b47efea9380302b..e34f565f595ae2d54613309af8013b2e735e9881 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c @@ -57,8 +57,6 @@ void (*ia64_mark_idle)(int); unsigned long boot_option_idle_override = IDLE_NO_OVERRIDE; EXPORT_SYMBOL(boot_option_idle_override); -void (*pm_idle) (void); -EXPORT_SYMBOL(pm_idle); void (*pm_power_off) (void); EXPORT_SYMBOL(pm_power_off); @@ -301,7 +299,6 @@ cpu_idle (void) if (mark_idle) (*mark_idle)(1); - idle = pm_idle; if (!idle) idle = default_idle; (*idle)(); diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index aaefd9b94f2fc6f57865b5d500bceaf50fdc84b3..2029cc0d2fc6f2b003c733b0c0d1ff42579e2083 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -1051,7 +1051,6 @@ cpu_init (void) max_num_phys_stacked = num_phys_stacked; } platform_cpu_init(); - pm_idle = default_idle; } void __init diff --git a/arch/m32r/kernel/process.c b/arch/m32r/kernel/process.c index 765d0f57c787e3777a520c9dcd079cca5cbbc4d6..bde899e155d3a682e6a396b74c7f9edf0e6ccd73 100644 --- a/arch/m32r/kernel/process.c +++ b/arch/m32r/kernel/process.c @@ -44,35 +44,9 @@ unsigned long thread_saved_pc(struct task_struct *tsk) return tsk->thread.lr; } -/* - * Powermanagement idle function, if any.. - */ -static void (*pm_idle)(void) = NULL; - void (*pm_power_off)(void) = NULL; EXPORT_SYMBOL(pm_power_off); -/* - * We use this is we don't have any better - * idle routine.. - */ -static void default_idle(void) -{ - /* M32R_FIXME: Please use "cpu_sleep" mode. */ - cpu_relax(); -} - -/* - * On SMP it's slightly faster (but much more power-consuming!) - * to poll the ->work.need_resched flag instead of waiting for the - * cross-CPU IPI to arrive. Use this option with caution. - */ -static void poll_idle (void) -{ - /* M32R_FIXME */ - cpu_relax(); -} - /* * The idle thread. There's no useful work to be * done, so just try to conserve power and have a @@ -84,14 +58,8 @@ void cpu_idle (void) /* endless idle loop with no priority at all */ while (1) { rcu_idle_enter(); - while (!need_resched()) { - void (*idle)(void) = pm_idle; - - if (!idle) - idle = default_idle; - - idle(); - } + while (!need_resched()) + cpu_relax(); rcu_idle_exit(); schedule_preempt_disabled(); } @@ -120,21 +88,6 @@ void machine_power_off(void) /* M32R_FIXME */ } -static int __init idle_setup (char *str) -{ - if (!strncmp(str, "poll", 4)) { - printk("using poll in idle threads.\n"); - pm_idle = poll_idle; - } else if (!strncmp(str, "sleep", 4)) { - printk("using sleep in idle threads.\n"); - pm_idle = default_idle; - } - - return 1; -} - -__setup("idle=", idle_setup); - void show_regs(struct pt_regs * regs) { printk("\n"); diff --git a/arch/microblaze/kernel/process.c b/arch/microblaze/kernel/process.c index a5b74f729e5bade2c12ca66fff5503161ad671f7..6ff2dcff3410ac854ac13258e87ca613a0472a53 100644 --- a/arch/microblaze/kernel/process.c +++ b/arch/microblaze/kernel/process.c @@ -41,7 +41,6 @@ void show_regs(struct pt_regs *regs) regs->msr, regs->ear, regs->esr, regs->fsr); } -void (*pm_idle)(void); void (*pm_power_off)(void) = NULL; EXPORT_SYMBOL(pm_power_off); @@ -98,8 +97,6 @@ void cpu_idle(void) /* endless idle loop with no priority at all */ while (1) { - void (*idle)(void) = pm_idle; - if (!idle) idle = default_idle; diff --git a/arch/mn10300/kernel/process.c b/arch/mn10300/kernel/process.c index eb09f5a552ff31efe426914715942d78f8f39e18..84f4e97e30745ad4d8e9b5d9e032dae5b775542b 100644 --- a/arch/mn10300/kernel/process.c +++ b/arch/mn10300/kernel/process.c @@ -36,12 +36,6 @@ #include #include "internal.h" -/* - * power management idle function, if any.. - */ -void (*pm_idle)(void); -EXPORT_SYMBOL(pm_idle); - /* * return saved PC of a blocked thread. */ @@ -113,7 +107,6 @@ void cpu_idle(void) void (*idle)(void); smp_rmb(); - idle = pm_idle; if (!idle) { #if defined(CONFIG_SMP) && !defined(CONFIG_HOTPLUG_CPU) idle = poll_idle; diff --git a/arch/openrisc/kernel/idle.c b/arch/openrisc/kernel/idle.c index 7d618feb1b72e360b909aeed3fc3dbd469e8091e..5e8a3b6d6bc693fda3ac794f48e4a66a374ee04d 100644 --- a/arch/openrisc/kernel/idle.c +++ b/arch/openrisc/kernel/idle.c @@ -39,11 +39,6 @@ void (*powersave) (void) = NULL; -static inline void pm_idle(void) -{ - barrier(); -} - void cpu_idle(void) { set_thread_flag(TIF_POLLING_NRFLAG); diff --git a/arch/sh/kernel/idle.c b/arch/sh/kernel/idle.c index 0c910163caa36d47436d1cb81f3974d20d11aeea..3d5a1b387cc0f48b23d569779769a39f735a0664 100644 --- a/arch/sh/kernel/idle.c +++ b/arch/sh/kernel/idle.c @@ -22,7 +22,7 @@ #include #include -void (*pm_idle)(void); +static void (*sh_idle)(void); static int hlt_counter; @@ -103,9 +103,9 @@ void cpu_idle(void) /* Don't trace irqs off for idle */ stop_critical_timings(); if (cpuidle_idle_call()) - pm_idle(); + sh_idle(); /* - * Sanity check to ensure that pm_idle() returns + * Sanity check to ensure that sh_idle() returns * with IRQs enabled */ WARN_ON(irqs_disabled()); @@ -123,13 +123,13 @@ void __init select_idle_routine(void) /* * If a platform has set its own idle routine, leave it alone. */ - if (pm_idle) + if (sh_idle) return; if (hlt_works()) - pm_idle = default_idle; + sh_idle = default_idle; else - pm_idle = poll_idle; + sh_idle = poll_idle; } void stop_this_cpu(void *unused) diff --git a/arch/sparc/include/asm/processor_32.h b/arch/sparc/include/asm/processor_32.h index c1e01914fd98b53c48a4aee32dccaa2e7fbb0c82..2c7baa4c45050f56d6f32afed6c99dd764c63729 100644 --- a/arch/sparc/include/asm/processor_32.h +++ b/arch/sparc/include/asm/processor_32.h @@ -118,6 +118,7 @@ extern unsigned long get_wchan(struct task_struct *); extern struct task_struct *last_task_used_math; #define cpu_relax() barrier() +extern void (*sparc_idle)(void); #endif diff --git a/arch/sparc/kernel/apc.c b/arch/sparc/kernel/apc.c index 348fa1aeabce586fd16ff03fcc89689d20358683..eefda32b595ef6ff1344d21ebc664ca4a7f9f0fa 100644 --- a/arch/sparc/kernel/apc.c +++ b/arch/sparc/kernel/apc.c @@ -20,6 +20,7 @@ #include #include #include +#include /* Debugging * @@ -158,7 +159,7 @@ static int apc_probe(struct platform_device *op) /* Assign power management IDLE handler */ if (!apc_no_idle) - pm_idle = apc_swift_idle; + sparc_idle = apc_swift_idle; printk(KERN_INFO "%s: power management initialized%s\n", APC_DEVNAME, apc_no_idle ? " (CPU idle disabled)" : ""); diff --git a/arch/sparc/kernel/leon_pmc.c b/arch/sparc/kernel/leon_pmc.c index 4e174321097d7a4af24eb0f5cd3bb4b1d5b37e53..708bca435219f1bf41853a250bd7a110f7f536be 100644 --- a/arch/sparc/kernel/leon_pmc.c +++ b/arch/sparc/kernel/leon_pmc.c @@ -9,6 +9,7 @@ #include #include #include +#include /* List of Systems that need fixup instructions around power-down instruction */ unsigned int pmc_leon_fixup_ids[] = { @@ -69,9 +70,9 @@ static int __init leon_pmc_install(void) if (sparc_cpu_model == sparc_leon) { /* Assign power management IDLE handler */ if (pmc_leon_need_fixup()) - pm_idle = pmc_leon_idle_fixup; + sparc_idle = pmc_leon_idle_fixup; else - pm_idle = pmc_leon_idle; + sparc_idle = pmc_leon_idle; printk(KERN_INFO "leon: power management initialized\n"); } diff --git a/arch/sparc/kernel/pmc.c b/arch/sparc/kernel/pmc.c index dcbb62f63068b53497393a959bfe5b063a014f60..8b7297faca79b18d24fd62cb32529d90ff27ab71 100644 --- a/arch/sparc/kernel/pmc.c +++ b/arch/sparc/kernel/pmc.c @@ -17,6 +17,7 @@ #include #include #include +#include /* Debug * @@ -63,7 +64,7 @@ static int pmc_probe(struct platform_device *op) #ifndef PMC_NO_IDLE /* Assign power management IDLE handler */ - pm_idle = pmc_swift_idle; + sparc_idle = pmc_swift_idle; #endif printk(KERN_INFO "%s: power management initialized\n", PMC_DEVNAME); diff --git a/arch/sparc/kernel/process_32.c b/arch/sparc/kernel/process_32.c index be8e862badaff0db6e4eb0ae8e9d6e93e18d429f..62eede13831a2685694986165c5ac11a36daceda 100644 --- a/arch/sparc/kernel/process_32.c +++ b/arch/sparc/kernel/process_32.c @@ -43,8 +43,7 @@ * Power management idle function * Set in pm platform drivers (apc.c and pmc.c) */ -void (*pm_idle)(void); -EXPORT_SYMBOL(pm_idle); +void (*sparc_idle)(void); /* * Power-off handler instantiation for pm.h compliance @@ -75,8 +74,8 @@ void cpu_idle(void) /* endless idle loop with no priority at all */ for (;;) { while (!need_resched()) { - if (pm_idle) - (*pm_idle)(); + if (sparc_idle) + (*sparc_idle)(); else cpu_relax(); } diff --git a/arch/unicore32/kernel/process.c b/arch/unicore32/kernel/process.c index 62bad9fed03e08ad494266664a805d73f467aaea..872d7e22d847e93eb4f1fa7f77bb9591d189e56a 100644 --- a/arch/unicore32/kernel/process.c +++ b/arch/unicore32/kernel/process.c @@ -45,11 +45,6 @@ static const char * const processor_modes[] = { "UK18", "UK19", "UK1A", "EXTN", "UK1C", "UK1D", "UK1E", "SUSR" }; -/* - * The idle thread, has rather strange semantics for calling pm_idle, - * but this is what x86 does and we need to do the same, so that - * things like cpuidle get called in the same way. - */ void cpu_idle(void) { /* endless idle loop with no priority at all */ diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 260857a53b87f7ffc149a285e1bff6f582493577..f7a27fdb509890096f2c4596ccec1bfe7541673b 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -469,6 +469,16 @@ config X86_MDFLD endif +config X86_INTEL_LPSS + bool "Intel Low Power Subsystem Support" + depends on ACPI + select COMMON_CLK + ---help--- + Select to build support for Intel Low Power Subsystem such as + found on Intel Lynxpoint PCH. Selecting this option enables + things like clock tree (common clock framework) which are needed + by the LPSS peripheral drivers. + config X86_RDC321X bool "RDC R-321x SoC" depends on X86_32 @@ -1927,6 +1937,7 @@ config APM_DO_ENABLE this feature. config APM_CPU_IDLE + depends on CPU_IDLE bool "Make CPU Idle calls when idle" ---help--- Enable calls to APM CPU Idle/CPU Busy inside the kernel's idle loop. diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h index 0c44630d17893e74a2672cf9e896c0a41b762c42..b31bf97775fcbeea3b29a9537092b24b379aba67 100644 --- a/arch/x86/include/asm/acpi.h +++ b/arch/x86/include/asm/acpi.h @@ -49,10 +49,6 @@ /* Asm macros */ -#define ACPI_ASM_MACROS -#define BREAKPOINT3 -#define ACPI_DISABLE_IRQS() local_irq_disable() -#define ACPI_ENABLE_IRQS() local_irq_enable() #define ACPI_FLUSH_CPU_CACHE() wbinvd() int __acpi_acquire_global_lock(unsigned int *lock); diff --git a/arch/x86/include/asm/mwait.h b/arch/x86/include/asm/mwait.h index bcdff997668c4e1f5f5440e397ff5c5f1ec33573..2f366d0ac6b4699b9e4bf5449f3fe7c8a95104bc 100644 --- a/arch/x86/include/asm/mwait.h +++ b/arch/x86/include/asm/mwait.h @@ -4,7 +4,8 @@ #define MWAIT_SUBSTATE_MASK 0xf #define MWAIT_CSTATE_MASK 0xf #define MWAIT_SUBSTATE_SIZE 4 -#define MWAIT_MAX_NUM_CSTATES 8 +#define MWAIT_HINT2CSTATE(hint) (((hint) >> MWAIT_SUBSTATE_SIZE) & MWAIT_CSTATE_MASK) +#define MWAIT_HINT2SUBSTATE(hint) ((hint) & MWAIT_CSTATE_MASK) #define CPUID_MWAIT_LEAF 5 #define CPUID5_ECX_EXTENSIONS_SUPPORTED 0x1 diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index cf500543f6ffd6334d67a8caaf93a80504d65699..d172588efae51b7cff0978106414a732e529b4de 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -89,7 +89,6 @@ struct cpuinfo_x86 { char wp_works_ok; /* It doesn't on 386's */ /* Problems on some 486Dx4's and old 386's: */ - char hlt_works_ok; char hard_math; char rfu; char fdiv_bug; @@ -165,15 +164,6 @@ DECLARE_PER_CPU_SHARED_ALIGNED(struct cpuinfo_x86, cpu_info); extern const struct seq_operations cpuinfo_op; -static inline int hlt_works(int cpu) -{ -#ifdef CONFIG_X86_32 - return cpu_data(cpu).hlt_works_ok; -#else - return 1; -#endif -} - #define cache_line_size() (boot_cpu_data.x86_cache_alignment) extern void cpu_detect(struct cpuinfo_x86 *c); @@ -725,7 +715,7 @@ extern unsigned long boot_option_idle_override; extern bool amd_e400_c1e_detected; enum idle_boot_override {IDLE_NO_OVERRIDE=0, IDLE_HALT, IDLE_NOMWAIT, - IDLE_POLL, IDLE_FORCE_MWAIT}; + IDLE_POLL}; extern void enable_sep_cpu(void); extern int sysenter_setup(void); @@ -998,7 +988,11 @@ extern unsigned long arch_align_stack(unsigned long sp); extern void free_init_pages(char *what, unsigned long begin, unsigned long end); void default_idle(void); -bool set_pm_idle_to_default(void); +#ifdef CONFIG_XEN +bool xen_set_default_idle(void); +#else +#define xen_set_default_idle 0 +#endif void stop_this_cpu(void *dummy); diff --git a/arch/x86/include/uapi/asm/msr-index.h b/arch/x86/include/uapi/asm/msr-index.h index 075a402555912541fe0b502c6c6b877812a5b089..f26d2771846f73d3968cd41c7fea2046864464d7 100644 --- a/arch/x86/include/uapi/asm/msr-index.h +++ b/arch/x86/include/uapi/asm/msr-index.h @@ -103,6 +103,8 @@ #define DEBUGCTLMSR_BTS_OFF_USR (1UL << 10) #define DEBUGCTLMSR_FREEZE_LBRS_ON_PMI (1UL << 11) +#define MSR_IA32_POWER_CTL 0x000001fc + #define MSR_IA32_MC0_CTL 0x00000400 #define MSR_IA32_MC0_STATUS 0x00000401 #define MSR_IA32_MC0_ADDR 0x00000402 @@ -274,6 +276,7 @@ #define MSR_IA32_PLATFORM_ID 0x00000017 #define MSR_IA32_EBL_CR_POWERON 0x0000002a #define MSR_EBC_FREQUENCY_ID 0x0000002c +#define MSR_SMI_COUNT 0x00000034 #define MSR_IA32_FEATURE_CONTROL 0x0000003a #define MSR_IA32_TSC_ADJUST 0x0000003b diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c index 8d7012b7f4020ffe3fc7cb7da0ed15cdfd05e5e7..66b5faffe14a983e7c39d201c3c50a4ef1126e32 100644 --- a/arch/x86/kernel/apm_32.c +++ b/arch/x86/kernel/apm_32.c @@ -232,6 +232,7 @@ #include #include #include +#include #include #include @@ -360,13 +361,35 @@ struct apm_user { * idle percentage above which bios idle calls are done */ #ifdef CONFIG_APM_CPU_IDLE -#warning deprecated CONFIG_APM_CPU_IDLE will be deleted in 2012 #define DEFAULT_IDLE_THRESHOLD 95 #else #define DEFAULT_IDLE_THRESHOLD 100 #endif #define DEFAULT_IDLE_PERIOD (100 / 3) +static int apm_cpu_idle(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index); + +static struct cpuidle_driver apm_idle_driver = { + .name = "apm_idle", + .owner = THIS_MODULE, + .en_core_tk_irqen = 1, + .states = { + { /* entry 0 is for polling */ }, + { /* entry 1 is for APM idle */ + .name = "APM", + .desc = "APM idle", + .flags = CPUIDLE_FLAG_TIME_VALID, + .exit_latency = 250, /* WAG */ + .target_residency = 500, /* WAG */ + .enter = &apm_cpu_idle + }, + }, + .state_count = 2, +}; + +static struct cpuidle_device apm_cpuidle_device; + /* * Local variables */ @@ -377,7 +400,6 @@ static struct { static int clock_slowed; static int idle_threshold __read_mostly = DEFAULT_IDLE_THRESHOLD; static int idle_period __read_mostly = DEFAULT_IDLE_PERIOD; -static int set_pm_idle; static int suspends_pending; static int standbys_pending; static int ignore_sys_suspend; @@ -884,8 +906,6 @@ static void apm_do_busy(void) #define IDLE_CALC_LIMIT (HZ * 100) #define IDLE_LEAKY_MAX 16 -static void (*original_pm_idle)(void) __read_mostly; - /** * apm_cpu_idle - cpu idling for APM capable Linux * @@ -894,7 +914,8 @@ static void (*original_pm_idle)(void) __read_mostly; * Furthermore it calls the system default idle routine. */ -static void apm_cpu_idle(void) +static int apm_cpu_idle(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index) { static int use_apm_idle; /* = 0 */ static unsigned int last_jiffies; /* = 0 */ @@ -905,7 +926,6 @@ static void apm_cpu_idle(void) unsigned int jiffies_since_last_check = jiffies - last_jiffies; unsigned int bucket; - WARN_ONCE(1, "deprecated apm_cpu_idle will be deleted in 2012"); recalc: task_cputime(current, NULL, &stime); if (jiffies_since_last_check > IDLE_CALC_LIMIT) { @@ -951,10 +971,7 @@ static void apm_cpu_idle(void) break; } } - if (original_pm_idle) - original_pm_idle(); - else - default_idle(); + default_idle(); local_irq_disable(); jiffies_since_last_check = jiffies - last_jiffies; if (jiffies_since_last_check > idle_period) @@ -964,7 +981,7 @@ static void apm_cpu_idle(void) if (apm_idle_done) apm_do_busy(); - local_irq_enable(); + return index; } /** @@ -2382,9 +2399,9 @@ static int __init apm_init(void) if (HZ != 100) idle_period = (idle_period * HZ) / 100; if (idle_threshold < 100) { - original_pm_idle = pm_idle; - pm_idle = apm_cpu_idle; - set_pm_idle = 1; + if (!cpuidle_register_driver(&apm_idle_driver)) + if (cpuidle_register_device(&apm_cpuidle_device)) + cpuidle_unregister_driver(&apm_idle_driver); } return 0; @@ -2394,15 +2411,9 @@ static void __exit apm_exit(void) { int error; - if (set_pm_idle) { - pm_idle = original_pm_idle; - /* - * We are about to unload the current idle thread pm callback - * (pm_idle), Wait for all processors to update cached/local - * copies of pm_idle before proceeding. - */ - kick_all_cpus_sync(); - } + cpuidle_unregister_device(&apm_cpuidle_device); + cpuidle_unregister_driver(&apm_idle_driver); + if (((apm_info.bios.flags & APM_BIOS_DISENGAGED) == 0) && (apm_info.connection_version > 0x0100)) { error = apm_engage_power_management(APM_DEVICE_ALL, 0); diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index 92dfec986a48ec97ffb680002f22a56f5a7b9262..af6455e3fcc9b9e6f7f1d75b6ee5ce112a689590 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -17,15 +17,6 @@ #include #include -static int __init no_halt(char *s) -{ - WARN_ONCE(1, "\"no-hlt\" is deprecated, please use \"idle=poll\"\n"); - boot_cpu_data.hlt_works_ok = 0; - return 1; -} - -__setup("no-hlt", no_halt); - static int __init no_387(char *s) { boot_cpu_data.hard_math = 0; @@ -89,23 +80,6 @@ static void __init check_fpu(void) pr_warn("Hmm, FPU with FDIV bug\n"); } -static void __init check_hlt(void) -{ - if (boot_cpu_data.x86 >= 5 || paravirt_enabled()) - return; - - pr_info("Checking 'hlt' instruction... "); - if (!boot_cpu_data.hlt_works_ok) { - pr_cont("disabled\n"); - return; - } - halt(); - halt(); - halt(); - halt(); - pr_cont("OK\n"); -} - /* * Check whether we are able to run this kernel safely on SMP. * @@ -129,7 +103,6 @@ void __init check_bugs(void) print_cpu_info(&boot_cpu_data); #endif check_config(); - check_hlt(); init_utsname()->machine[1] = '0' + (boot_cpu_data.x86 > 6 ? 6 : boot_cpu_data.x86); alternative_instructions(); diff --git a/arch/x86/kernel/cpu/proc.c b/arch/x86/kernel/cpu/proc.c index 3286a92e662a13a4e146cbe73912c8f239427007..e280253f6f9415ed10ff36cde95fc2f48238d29a 100644 --- a/arch/x86/kernel/cpu/proc.c +++ b/arch/x86/kernel/cpu/proc.c @@ -28,7 +28,6 @@ static void show_cpuinfo_misc(struct seq_file *m, struct cpuinfo_x86 *c) { seq_printf(m, "fdiv_bug\t: %s\n" - "hlt_bug\t\t: %s\n" "f00f_bug\t: %s\n" "coma_bug\t: %s\n" "fpu\t\t: %s\n" @@ -36,7 +35,6 @@ static void show_cpuinfo_misc(struct seq_file *m, struct cpuinfo_x86 *c) "cpuid level\t: %d\n" "wp\t\t: %s\n", c->fdiv_bug ? "yes" : "no", - c->hlt_works_ok ? "no" : "yes", c->f00f_bug ? "yes" : "no", c->coma_bug ? "yes" : "no", c->hard_math ? "yes" : "no", diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 2ed787f15bf0cf397d6515c429d50544e04e9e34..14ae10031ff04ba1bbfca4ea6064b6260badb4b3 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -268,13 +268,7 @@ void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, unsigned long boot_option_idle_override = IDLE_NO_OVERRIDE; EXPORT_SYMBOL(boot_option_idle_override); -/* - * Powermanagement idle function, if any.. - */ -void (*pm_idle)(void); -#ifdef CONFIG_APM_MODULE -EXPORT_SYMBOL(pm_idle); -#endif +static void (*x86_idle)(void); #ifndef CONFIG_SMP static inline void play_dead(void) @@ -351,7 +345,7 @@ void cpu_idle(void) rcu_idle_enter(); if (cpuidle_idle_call()) - pm_idle(); + x86_idle(); rcu_idle_exit(); start_critical_timings(); @@ -375,7 +369,6 @@ void cpu_idle(void) */ void default_idle(void) { - trace_power_start_rcuidle(POWER_CSTATE, 1, smp_processor_id()); trace_cpu_idle_rcuidle(1, smp_processor_id()); current_thread_info()->status &= ~TS_POLLING; /* @@ -389,21 +382,22 @@ void default_idle(void) else local_irq_enable(); current_thread_info()->status |= TS_POLLING; - trace_power_end_rcuidle(smp_processor_id()); trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, smp_processor_id()); } #ifdef CONFIG_APM_MODULE EXPORT_SYMBOL(default_idle); #endif -bool set_pm_idle_to_default(void) +#ifdef CONFIG_XEN +bool xen_set_default_idle(void) { - bool ret = !!pm_idle; + bool ret = !!x86_idle; - pm_idle = default_idle; + x86_idle = default_idle; return ret; } +#endif void stop_this_cpu(void *dummy) { local_irq_disable(); @@ -413,31 +407,8 @@ void stop_this_cpu(void *dummy) set_cpu_online(smp_processor_id(), false); disable_local_APIC(); - for (;;) { - if (hlt_works(smp_processor_id())) - halt(); - } -} - -/* Default MONITOR/MWAIT with no hints, used for default C1 state */ -static void mwait_idle(void) -{ - if (!need_resched()) { - trace_power_start_rcuidle(POWER_CSTATE, 1, smp_processor_id()); - trace_cpu_idle_rcuidle(1, smp_processor_id()); - if (this_cpu_has(X86_FEATURE_CLFLUSH_MONITOR)) - clflush((void *)¤t_thread_info()->flags); - - __monitor((void *)¤t_thread_info()->flags, 0, 0); - smp_mb(); - if (!need_resched()) - __sti_mwait(0, 0); - else - local_irq_enable(); - trace_power_end_rcuidle(smp_processor_id()); - trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, smp_processor_id()); - } else - local_irq_enable(); + for (;;) + halt(); } /* @@ -447,62 +418,13 @@ static void mwait_idle(void) */ static void poll_idle(void) { - trace_power_start_rcuidle(POWER_CSTATE, 0, smp_processor_id()); trace_cpu_idle_rcuidle(0, smp_processor_id()); local_irq_enable(); while (!need_resched()) cpu_relax(); - trace_power_end_rcuidle(smp_processor_id()); trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, smp_processor_id()); } -/* - * mwait selection logic: - * - * It depends on the CPU. For AMD CPUs that support MWAIT this is - * wrong. Family 0x10 and 0x11 CPUs will enter C1 on HLT. Powersavings - * then depend on a clock divisor and current Pstate of the core. If - * all cores of a processor are in halt state (C1) the processor can - * enter the C1E (C1 enhanced) state. If mwait is used this will never - * happen. - * - * idle=mwait overrides this decision and forces the usage of mwait. - */ - -#define MWAIT_INFO 0x05 -#define MWAIT_ECX_EXTENDED_INFO 0x01 -#define MWAIT_EDX_C1 0xf0 - -int mwait_usable(const struct cpuinfo_x86 *c) -{ - u32 eax, ebx, ecx, edx; - - /* Use mwait if idle=mwait boot option is given */ - if (boot_option_idle_override == IDLE_FORCE_MWAIT) - return 1; - - /* - * Any idle= boot option other than idle=mwait means that we must not - * use mwait. Eg: idle=halt or idle=poll or idle=nomwait - */ - if (boot_option_idle_override != IDLE_NO_OVERRIDE) - return 0; - - if (c->cpuid_level < MWAIT_INFO) - return 0; - - cpuid(MWAIT_INFO, &eax, &ebx, &ecx, &edx); - /* Check, whether EDX has extended info about MWAIT */ - if (!(ecx & MWAIT_ECX_EXTENDED_INFO)) - return 1; - - /* - * edx enumeratios MONITOR/MWAIT extensions. Check, whether - * C1 supports MWAIT - */ - return (edx & MWAIT_EDX_C1); -} - bool amd_e400_c1e_detected; EXPORT_SYMBOL(amd_e400_c1e_detected); @@ -567,31 +489,24 @@ static void amd_e400_idle(void) void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c) { #ifdef CONFIG_SMP - if (pm_idle == poll_idle && smp_num_siblings > 1) { + if (x86_idle == poll_idle && smp_num_siblings > 1) pr_warn_once("WARNING: polling idle and HT enabled, performance may degrade\n"); - } #endif - if (pm_idle) + if (x86_idle) return; - if (cpu_has(c, X86_FEATURE_MWAIT) && mwait_usable(c)) { - /* - * One CPU supports mwait => All CPUs supports mwait - */ - pr_info("using mwait in idle threads\n"); - pm_idle = mwait_idle; - } else if (cpu_has_amd_erratum(amd_erratum_400)) { + if (cpu_has_amd_erratum(amd_erratum_400)) { /* E400: APIC timer interrupt does not wake up CPU from C1e */ pr_info("using AMD E400 aware idle routine\n"); - pm_idle = amd_e400_idle; + x86_idle = amd_e400_idle; } else - pm_idle = default_idle; + x86_idle = default_idle; } void __init init_amd_e400_c1e_mask(void) { /* If we're using amd_e400_idle, we need to allocate amd_e400_c1e_mask. */ - if (pm_idle == amd_e400_idle) + if (x86_idle == amd_e400_idle) zalloc_cpumask_var(&amd_e400_c1e_mask, GFP_KERNEL); } @@ -602,11 +517,8 @@ static int __init idle_setup(char *str) if (!strcmp(str, "poll")) { pr_info("using polling idle threads\n"); - pm_idle = poll_idle; + x86_idle = poll_idle; boot_option_idle_override = IDLE_POLL; - } else if (!strcmp(str, "mwait")) { - boot_option_idle_override = IDLE_FORCE_MWAIT; - WARN_ONCE(1, "\"idle=mwait\" will be removed in 2012\n"); } else if (!strcmp(str, "halt")) { /* * When the boot option of idle=halt is added, halt is @@ -615,7 +527,7 @@ static int __init idle_setup(char *str) * To continue to load the CPU idle driver, don't touch * the boot_option_idle_override. */ - pm_idle = default_idle; + x86_idle = default_idle; boot_option_idle_override = IDLE_HALT; } else if (!strcmp(str, "nomwait")) { /* diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index ed0fe385289d1db348aaee1bae1e9f2aa63d1c5e..a6ceaedc396a2d67f3514e3f162a614b5444cd74 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -1369,7 +1369,7 @@ static inline void mwait_play_dead(void) void *mwait_ptr; struct cpuinfo_x86 *c = __this_cpu_ptr(&cpu_info); - if (!(this_cpu_has(X86_FEATURE_MWAIT) && mwait_usable(c))) + if (!this_cpu_has(X86_FEATURE_MWAIT)) return; if (!this_cpu_has(X86_FEATURE_CLFLSH)) return; diff --git a/arch/x86/platform/olpc/olpc-xo15-sci.c b/arch/x86/platform/olpc/olpc-xo15-sci.c index 2fdca25905ae265c52a2695664da433e57e1b616..fef7d0ba7e3a93d8e44ed09cec92db708759cbcf 100644 --- a/arch/x86/platform/olpc/olpc-xo15-sci.c +++ b/arch/x86/platform/olpc/olpc-xo15-sci.c @@ -195,7 +195,7 @@ static int xo15_sci_add(struct acpi_device *device) return r; } -static int xo15_sci_remove(struct acpi_device *device, int type) +static int xo15_sci_remove(struct acpi_device *device) { acpi_disable_gpe(NULL, xo15_sci_gpe); acpi_remove_gpe_handler(NULL, xo15_sci_gpe, xo15_sci_gpe_handler); diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c index 8971a26d21abb943d5c9e23b5c6630a207f43536..94eac5c85cdc9eea7b32ac1d07d94252cac3087e 100644 --- a/arch/x86/xen/setup.c +++ b/arch/x86/xen/setup.c @@ -556,12 +556,9 @@ void __init xen_arch_setup(void) COMMAND_LINE_SIZE : MAX_GUEST_CMDLINE); /* Set up idle, making sure it calls safe_halt() pvop */ -#ifdef CONFIG_X86_32 - boot_cpu_data.hlt_works_ok = 1; -#endif disable_cpuidle(); disable_cpufreq(); - WARN_ON(set_pm_idle_to_default()); + WARN_ON(xen_set_default_idle()); fiddle_vdso(); #ifdef CONFIG_NUMA numa_off = 1; diff --git a/drivers/Kconfig b/drivers/Kconfig index f5fb0722a63a14c9155b58a86f69c82e6efa8d92..2b4e89ba15adafe1f6105c2dd06d5cfe0beaa8d1 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -134,6 +134,8 @@ source "drivers/hwspinlock/Kconfig" source "drivers/clocksource/Kconfig" +source "drivers/mailbox/Kconfig" + source "drivers/iommu/Kconfig" source "drivers/remoteproc/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index 7863b9fee50bbc33793a2acb2f104c34c22b2bd0..a8d32f1094b4dca4204918c053e1aaa87a6babb9 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -130,6 +130,7 @@ obj-y += platform/ #common clk code obj-y += clk/ +obj-$(CONFIG_MAILBOX) += mailbox/ obj-$(CONFIG_HWSPINLOCK) += hwspinlock/ obj-$(CONFIG_NFC) += nfc/ obj-$(CONFIG_IOMMU_SUPPORT) += iommu/ diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 38c5078da11d67ea9db98cf936812982b62f313c..78105b3a52623e9b22be90f71dcaa5b1ae33b725 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -337,7 +337,7 @@ config X86_PM_TIMER systems require this timer. config ACPI_CONTAINER - tristate "Container and Module Devices (EXPERIMENTAL)" + bool "Container and Module Devices (EXPERIMENTAL)" depends on EXPERIMENTAL default (ACPI_HOTPLUG_MEMORY || ACPI_HOTPLUG_CPU || ACPI_HOTPLUG_IO) help diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 2a4502becd1356cefc5e9b36fc0942a5772eb4ef..474fcfeba66c45f2f8fb511c27e2e68f605b9988 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -37,7 +37,8 @@ acpi-y += resource.o acpi-y += processor_core.o acpi-y += ec.o acpi-$(CONFIG_ACPI_DOCK) += dock.o -acpi-y += pci_root.o pci_link.o pci_irq.o pci_bind.o +acpi-y += pci_root.o pci_link.o pci_irq.o +acpi-y += csrt.o acpi-y += acpi_platform.o acpi-y += power.o acpi-y += event.o diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index d5fdd36190cce3f385011b30a1f5c729a5b6a4dd..6d5bf649196dced64c75614fc586f1b16684e7bd 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -60,7 +60,7 @@ 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, int type); +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[] = { @@ -337,7 +337,7 @@ static int acpi_ac_resume(struct device *dev) } #endif -static int acpi_ac_remove(struct acpi_device *device, int type) +static int acpi_ac_remove(struct acpi_device *device) { struct acpi_ac *ac = NULL; diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index b679bf8478f7a4bd3483127853cceb75185f97aa..034d3e72aa92d6dca344a5da1a756571ad3cc0f8 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c @@ -54,7 +54,7 @@ MODULE_LICENSE("GPL"); #define MEMORY_POWER_OFF_STATE 2 static int acpi_memory_device_add(struct acpi_device *device); -static int acpi_memory_device_remove(struct acpi_device *device, int type); +static int acpi_memory_device_remove(struct acpi_device *device); static const struct acpi_device_id memory_device_ids[] = { {ACPI_MEMORY_DEVICE_HID, 0}, @@ -153,51 +153,46 @@ acpi_memory_get_device_resources(struct acpi_memory_device *mem_device) return 0; } -static int -acpi_memory_get_device(acpi_handle handle, - struct acpi_memory_device **mem_device) +static int acpi_memory_get_device(acpi_handle handle, + struct acpi_memory_device **mem_device) { - acpi_status status; - acpi_handle phandle; struct acpi_device *device = NULL; - struct acpi_device *pdevice = NULL; - int result; + int result = 0; + acpi_scan_lock_acquire(); - if (!acpi_bus_get_device(handle, &device) && device) + acpi_bus_get_device(handle, &device); + if (device) goto end; - status = acpi_get_parent(handle, &phandle); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Cannot find acpi parent")); - return -EINVAL; - } - - /* Get the parent device */ - result = acpi_bus_get_device(phandle, &pdevice); - if (result) { - acpi_handle_warn(phandle, "Cannot get acpi bus device\n"); - return -EINVAL; - } - /* * Now add the notified device. This creates the acpi_device * and invokes .add function */ - result = acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE); + result = acpi_bus_scan(handle); if (result) { - acpi_handle_warn(handle, "Cannot add acpi bus\n"); - return -EINVAL; + acpi_handle_warn(handle, "ACPI namespace scan failed\n"); + result = -EINVAL; + goto out; + } + result = acpi_bus_get_device(handle, &device); + if (result) { + acpi_handle_warn(handle, "Missing device object\n"); + result = -EINVAL; + goto out; } - end: + end: *mem_device = acpi_driver_data(device); if (!(*mem_device)) { dev_err(&device->dev, "driver data not found\n"); - return -ENODEV; + result = -ENODEV; + goto out; } - return 0; + out: + acpi_scan_lock_release(); + return result; } static int acpi_memory_check_device(struct acpi_memory_device *mem_device) @@ -317,6 +312,7 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data) struct acpi_device *device; struct acpi_eject_event *ej_event = NULL; u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */ + acpi_status status; switch (event) { case ACPI_NOTIFY_BUS_CHECK: @@ -339,29 +335,40 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data) ACPI_DEBUG_PRINT((ACPI_DB_INFO, "\nReceived EJECT REQUEST notification for device\n")); + status = AE_ERROR; + acpi_scan_lock_acquire(); + if (acpi_bus_get_device(handle, &device)) { acpi_handle_err(handle, "Device doesn't exist\n"); - break; + goto unlock; } mem_device = acpi_driver_data(device); if (!mem_device) { acpi_handle_err(handle, "Driver Data is NULL\n"); - break; + goto unlock; } ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL); if (!ej_event) { pr_err(PREFIX "No memory, dropping EJECT\n"); - break; + goto unlock; } - ej_event->handle = handle; + get_device(&device->dev); + ej_event->device = device; ej_event->event = ACPI_NOTIFY_EJECT_REQUEST; - acpi_os_hotplug_execute(acpi_bus_hot_remove_device, - (void *)ej_event); + /* The eject is carried out asynchronously. */ + status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, + ej_event); + if (ACPI_FAILURE(status)) { + put_device(&device->dev); + kfree(ej_event); + } - /* eject is performed asynchronously */ - return; + unlock: + acpi_scan_lock_release(); + if (ACPI_SUCCESS(status)) + return; default: ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unsupported event [0x%x]\n", event)); @@ -372,7 +379,6 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data) /* Inform firmware that the hotplug operation has completed */ (void) acpi_evaluate_hotplug_ost(handle, event, ost_code, NULL); - return; } static void acpi_memory_device_free(struct acpi_memory_device *mem_device) @@ -427,7 +433,7 @@ static int acpi_memory_device_add(struct acpi_device *device) return result; } -static int acpi_memory_device_remove(struct acpi_device *device, int type) +static int acpi_memory_device_remove(struct acpi_device *device) { struct acpi_memory_device *mem_device = NULL; int result; diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c index 16fa979f7180b935a52fbfa03c75ca173359031d..31de1043eea051ca34859193b5ae0afd9d70c2d5 100644 --- a/drivers/acpi/acpi_pad.c +++ b/drivers/acpi/acpi_pad.c @@ -482,8 +482,7 @@ static int acpi_pad_add(struct acpi_device *device) return 0; } -static int acpi_pad_remove(struct acpi_device *device, - int type) +static int acpi_pad_remove(struct acpi_device *device) { mutex_lock(&isolated_cpus_lock); acpi_pad_idle_cpus(0); diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c index db129b9f52cba6c8634439fd2f753ec10bc1246e..26fce4b8a632a3b8537f4baa16ae36f84d6530d1 100644 --- a/drivers/acpi/acpi_platform.c +++ b/drivers/acpi/acpi_platform.c @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -21,18 +22,59 @@ ACPI_MODULE_NAME("platform"); +/* Flags for acpi_create_platform_device */ +#define ACPI_PLATFORM_CLK BIT(0) + +/* + * The following ACPI IDs are known to be suitable for representing as + * platform devices. + */ +static const struct acpi_device_id acpi_platform_device_ids[] = { + + { "PNP0D40" }, + + /* Haswell LPSS devices */ + { "INT33C0", ACPI_PLATFORM_CLK }, + { "INT33C1", ACPI_PLATFORM_CLK }, + { "INT33C2", ACPI_PLATFORM_CLK }, + { "INT33C3", ACPI_PLATFORM_CLK }, + { "INT33C4", ACPI_PLATFORM_CLK }, + { "INT33C5", ACPI_PLATFORM_CLK }, + { "INT33C6", ACPI_PLATFORM_CLK }, + { "INT33C7", ACPI_PLATFORM_CLK }, + + { } +}; + +static int acpi_create_platform_clks(struct acpi_device *adev) +{ + static struct platform_device *pdev; + + /* Create Lynxpoint LPSS clocks */ + if (!pdev && !strncmp(acpi_device_hid(adev), "INT33C", 6)) { + pdev = platform_device_register_simple("clk-lpt", -1, NULL, 0); + if (IS_ERR(pdev)) + return PTR_ERR(pdev); + } + + return 0; +} + /** * acpi_create_platform_device - Create platform device for ACPI device node * @adev: ACPI device node to create a platform device for. + * @id: ACPI device ID used to match @adev. * * Check if the given @adev can be represented as a platform device and, if * that's the case, create and register a platform device, populate its common * resources and returns a pointer to it. Otherwise, return %NULL. * - * The platform device's name will be taken from the @adev's _HID and _UID. + * Name of the platform device will be the same as @adev's. */ -struct platform_device *acpi_create_platform_device(struct acpi_device *adev) +static int acpi_create_platform_device(struct acpi_device *adev, + const struct acpi_device_id *id) { + unsigned long flags = id->driver_data; struct platform_device *pdev = NULL; struct acpi_device *acpi_parent; struct platform_device_info pdevinfo; @@ -41,20 +83,28 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev) struct resource *resources; int count; + if (flags & ACPI_PLATFORM_CLK) { + int ret = acpi_create_platform_clks(adev); + if (ret) { + dev_err(&adev->dev, "failed to create clocks\n"); + return ret; + } + } + /* If the ACPI node already has a physical device attached, skip it. */ if (adev->physical_node_count) - return NULL; + return 0; INIT_LIST_HEAD(&resource_list); count = acpi_dev_get_resources(adev, &resource_list, NULL, NULL); if (count <= 0) - return NULL; + return 0; resources = kmalloc(count * sizeof(struct resource), GFP_KERNEL); if (!resources) { dev_err(&adev->dev, "No memory for resources\n"); acpi_dev_free_resource_list(&resource_list); - return NULL; + return -ENOMEM; } count = 0; list_for_each_entry(rentry, &resource_list, node) @@ -100,5 +150,15 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev) } kfree(resources); - return pdev; + return 1; +} + +static struct acpi_scan_handler platform_handler = { + .ids = acpi_platform_device_ids, + .attach = acpi_create_platform_device, +}; + +void __init acpi_platform_init(void) +{ + acpi_scan_add_handler(&platform_handler); } diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile index bc7a03ded064520fd88d64a4d335bf1d0a6813e8..a1b9bf5085a287c8fd38804d85e28b62ea7b76a5 100644 --- a/drivers/acpi/acpica/Makefile +++ b/drivers/acpi/acpica/Makefile @@ -31,6 +31,7 @@ acpi-y += \ evgpeinit.o \ evgpeutil.o \ evglock.o \ + evhandler.o \ evmisc.o \ evregion.o \ evrgnini.o \ @@ -90,6 +91,7 @@ acpi-y += \ nsobject.o \ nsparse.o \ nspredef.o \ + nsprepkg.o \ nsrepair.o \ nsrepair2.o \ nssearch.o \ @@ -104,7 +106,9 @@ acpi-$(ACPI_FUTURE_USAGE) += nsdumpdv.o acpi-y += \ psargs.o \ psloop.o \ + psobject.o \ psopcode.o \ + psopinfo.o \ psparse.o \ psscope.o \ pstree.o \ @@ -126,7 +130,7 @@ acpi-y += \ rsutils.o \ rsxface.o -acpi-$(ACPI_FUTURE_USAGE) += rsdump.o +acpi-$(ACPI_FUTURE_USAGE) += rsdump.o rsdumpinfo.o acpi-y += \ tbfadt.o \ @@ -155,8 +159,10 @@ acpi-y += \ utmutex.o \ utobject.o \ utosi.o \ + utownerid.o \ utresrc.o \ utstate.o \ + utstring.o \ utxface.o \ utxfinit.o \ utxferror.o \ diff --git a/drivers/acpi/acpica/accommon.h b/drivers/acpi/acpica/accommon.h index 8a7d51bfb3b39632f6f5a46f5b0bb469dfab7b86..8a6c4a0d22db7b2dc5b8250c91880a60e74bfbb3 100644 --- a/drivers/acpi/acpica/accommon.h +++ b/drivers/acpi/acpica/accommon.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -51,6 +51,7 @@ * * Note: The order of these include files is important. */ +#include /* Global configuration constants */ #include "acmacros.h" /* C macros */ #include "aclocal.h" /* Internal data types */ #include "acobject.h" /* ACPI internal object */ diff --git a/drivers/acpi/acpica/acdebug.h b/drivers/acpi/acpica/acdebug.h index 432a318c9ed1cd33d599b135663945ef2313acd3..9feba08c29fe08b772e976fdefc7531300eb4d2d 100644 --- a/drivers/acpi/acpica/acdebug.h +++ b/drivers/acpi/acpica/acdebug.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -114,6 +114,21 @@ ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_db_generate_gpe(char *gpe_arg, char *block_arg)) +/* + * dbconvert - miscellaneous conversion routines + */ + 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); + +acpi_status +acpi_db_convert_to_object(acpi_object_type type, + char *string, union acpi_object *object); + +u8 *acpi_db_encode_pld_buffer(struct acpi_pld_info *pld_info); + +void acpi_db_dump_pld_buffer(union acpi_object *obj_desc); + /* * dbmethod - control method commands */ @@ -191,6 +206,8 @@ void acpi_db_create_execution_threads(char *num_threads_arg, char *num_loops_arg, char *method_name_arg); +void acpi_db_delete_objects(u32 count, union acpi_object *objects); + #ifdef ACPI_DBG_TRACK_ALLOCATIONS u32 acpi_db_get_cache_info(struct acpi_memory_list *cache); #endif diff --git a/drivers/acpi/acpica/acdispat.h b/drivers/acpi/acpica/acdispat.h index ed33ebcdaebebae3ee86bb0876b1e0b9892bb15b..427db72a6302f4b53f32a71d44a8a0f0ef170b27 100644 --- a/drivers/acpi/acpica/acdispat.h +++ b/drivers/acpi/acpica/acdispat.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h index e975c672044844bb56fa74ff137f66455b9fbaca..ab0e9771038127c83365fc3b1d72de841612fb99 100644 --- a/drivers/acpi/acpica/acevents.h +++ b/drivers/acpi/acpica/acevents.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -158,10 +158,23 @@ acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info, void *context); /* - * evregion - Address Space handling + * evhandler - Address space handling */ +u8 +acpi_ev_has_default_handler(struct acpi_namespace_node *node, + acpi_adr_space_type space_id); + acpi_status acpi_ev_install_region_handlers(void); +acpi_status +acpi_ev_install_space_handler(struct acpi_namespace_node *node, + acpi_adr_space_type space_id, + acpi_adr_space_handler handler, + acpi_adr_space_setup setup, void *context); + +/* + * evregion - Operation region support + */ acpi_status acpi_ev_initialize_op_regions(void); acpi_status @@ -179,12 +192,6 @@ void acpi_ev_detach_region(union acpi_operand_object *region_obj, u8 acpi_ns_is_locked); -acpi_status -acpi_ev_install_space_handler(struct acpi_namespace_node *node, - acpi_adr_space_type space_id, - acpi_adr_space_handler handler, - acpi_adr_space_setup setup, void *context); - acpi_status acpi_ev_execute_reg_methods(struct acpi_namespace_node *node, acpi_adr_space_type space_id); diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index 64472e4ec3294aff5ea263a7efd1568bb121ba6a..ecb49927b817a8892b3c3431406a7abbd42b0a16 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -192,14 +192,6 @@ ACPI_EXTERN u8 acpi_gbl_integer_bit_width; ACPI_EXTERN u8 acpi_gbl_integer_byte_width; ACPI_EXTERN u8 acpi_gbl_integer_nybble_width; -/* Mutex for _OSI support */ - -ACPI_EXTERN acpi_mutex acpi_gbl_osi_mutex; - -/* Reader/Writer lock is used for namespace walk and dynamic table unload */ - -ACPI_EXTERN struct acpi_rw_lock acpi_gbl_namespace_rw_lock; - /***************************************************************************** * * Mutual exclusion within ACPICA subsystem @@ -233,6 +225,14 @@ ACPI_EXTERN u8 acpi_gbl_global_lock_pending; ACPI_EXTERN acpi_spinlock acpi_gbl_gpe_lock; /* For GPE data structs and registers */ ACPI_EXTERN acpi_spinlock acpi_gbl_hardware_lock; /* For ACPI H/W except GPE registers */ +/* Mutex for _OSI support */ + +ACPI_EXTERN acpi_mutex acpi_gbl_osi_mutex; + +/* Reader/Writer lock is used for namespace walk and dynamic table unload */ + +ACPI_EXTERN struct acpi_rw_lock acpi_gbl_namespace_rw_lock; + /***************************************************************************** * * Miscellaneous globals @@ -252,7 +252,7 @@ ACPI_EXTERN acpi_cache_t *acpi_gbl_operand_cache; ACPI_EXTERN struct acpi_global_notify_handler acpi_gbl_global_notify[2]; ACPI_EXTERN acpi_exception_handler acpi_gbl_exception_handler; ACPI_EXTERN acpi_init_handler acpi_gbl_init_handler; -ACPI_EXTERN acpi_tbl_handler acpi_gbl_table_handler; +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; @@ -304,6 +304,7 @@ extern const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS]; ACPI_EXTERN struct acpi_memory_list *acpi_gbl_global_list; ACPI_EXTERN struct acpi_memory_list *acpi_gbl_ns_node_list; ACPI_EXTERN u8 acpi_gbl_display_final_mem_stats; +ACPI_EXTERN u8 acpi_gbl_disable_mem_tracking; #endif /***************************************************************************** @@ -365,19 +366,18 @@ ACPI_EXTERN u8 acpi_gbl_sleep_type_b; * ****************************************************************************/ -extern struct acpi_fixed_event_info - acpi_gbl_fixed_event_info[ACPI_NUM_FIXED_EVENTS]; -ACPI_EXTERN struct acpi_fixed_event_handler - acpi_gbl_fixed_event_handlers[ACPI_NUM_FIXED_EVENTS]; -ACPI_EXTERN struct acpi_gpe_xrupt_info *acpi_gbl_gpe_xrupt_list_head; -ACPI_EXTERN struct acpi_gpe_block_info -*acpi_gbl_gpe_fadt_blocks[ACPI_MAX_GPE_BLOCKS]; - #if (!ACPI_REDUCED_HARDWARE) ACPI_EXTERN u8 acpi_gbl_all_gpes_initialized; +ACPI_EXTERN struct acpi_gpe_xrupt_info *acpi_gbl_gpe_xrupt_list_head; +ACPI_EXTERN struct acpi_gpe_block_info + *acpi_gbl_gpe_fadt_blocks[ACPI_MAX_GPE_BLOCKS]; ACPI_EXTERN acpi_gbl_event_handler acpi_gbl_global_event_handler; ACPI_EXTERN void *acpi_gbl_global_event_handler_context; +ACPI_EXTERN struct acpi_fixed_event_handler + acpi_gbl_fixed_event_handlers[ACPI_NUM_FIXED_EVENTS]; +extern struct acpi_fixed_event_info + acpi_gbl_fixed_event_info[ACPI_NUM_FIXED_EVENTS]; #endif /* !ACPI_REDUCED_HARDWARE */ @@ -405,7 +405,7 @@ ACPI_EXTERN u32 acpi_gbl_trace_dbg_layer; /***************************************************************************** * - * Debugger globals + * Debugger and Disassembler globals * ****************************************************************************/ @@ -413,8 +413,12 @@ ACPI_EXTERN u8 acpi_gbl_db_output_flags; #ifdef ACPI_DISASSEMBLER +u8 ACPI_INIT_GLOBAL(acpi_gbl_ignore_noop_operator, FALSE); + ACPI_EXTERN u8 acpi_gbl_db_opt_disasm; ACPI_EXTERN u8 acpi_gbl_db_opt_verbose; +ACPI_EXTERN struct acpi_external_list *acpi_gbl_external_list; +ACPI_EXTERN struct acpi_external_file *acpi_gbl_external_file_list; #endif #ifdef ACPI_DEBUGGER @@ -426,6 +430,7 @@ extern u8 acpi_gbl_db_terminate_threads; 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]; diff --git a/drivers/acpi/acpica/achware.h b/drivers/acpi/acpica/achware.h index d902d31abc6c5ec1957b14990cf3a4f57e13f7a0..6357e932bfd9d20cf6640dd1a87c86e95969bac2 100644 --- a/drivers/acpi/acpica/achware.h +++ b/drivers/acpi/acpica/achware.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/acinterp.h b/drivers/acpi/acpica/acinterp.h index eb308635da7247f0e1ae0554f322d082869b3eb9..8af8c9bdeb3552b115617b3507c7b0d1ef602c59 100644 --- a/drivers/acpi/acpica/acinterp.h +++ b/drivers/acpi/acpica/acinterp.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -458,7 +458,7 @@ void acpi_ex_reacquire_interpreter(void); void acpi_ex_relinquish_interpreter(void); -void acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc); +u8 acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc); void acpi_ex_acquire_global_lock(u32 rule); diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index ff8bd0061e8bf8e40eb40d5f4603910b4a787fa3..805f419086ab596f2b268be0f135ddb4bcb17913 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -189,11 +189,10 @@ struct acpi_namespace_node { #define ANOBJ_EVALUATED 0x20 /* Set on first evaluation of node */ #define ANOBJ_ALLOCATED_BUFFER 0x40 /* Method AML buffer is dynamic (install_method) */ -#define ANOBJ_IS_EXTERNAL 0x08 /* i_aSL only: This object created via External() */ -#define ANOBJ_METHOD_NO_RETVAL 0x10 /* i_aSL only: Method has no return value */ -#define ANOBJ_METHOD_SOME_NO_RETVAL 0x20 /* i_aSL only: Method has at least one return value */ -#define ANOBJ_IS_BIT_OFFSET 0x40 /* i_aSL only: Reference is a bit offset */ -#define ANOBJ_IS_REFERENCED 0x80 /* i_aSL only: Object was referenced */ +#define ANOBJ_IS_EXTERNAL 0x08 /* iASL only: This object created via External() */ +#define ANOBJ_METHOD_NO_RETVAL 0x10 /* iASL only: Method has no return value */ +#define ANOBJ_METHOD_SOME_NO_RETVAL 0x20 /* iASL only: Method has at least one return value */ +#define ANOBJ_IS_REFERENCED 0x80 /* iASL only: Object was referenced */ /* Internal ACPI table management - master table list */ @@ -411,11 +410,10 @@ struct acpi_gpe_notify_info { struct acpi_gpe_notify_info *next; }; -struct acpi_gpe_notify_object { - struct acpi_namespace_node *node; - struct acpi_gpe_notify_object *next; -}; - +/* + * GPE dispatch info. At any time, the GPE can have at most one type + * of dispatch - Method, Handler, or Implicit Notify. + */ union acpi_gpe_dispatch_info { struct acpi_namespace_node *method_node; /* Method node for this GPE level */ struct acpi_gpe_handler_info *handler; /* Installed GPE handler */ @@ -679,6 +677,8 @@ struct acpi_opcode_info { u8 type; /* Opcode type */ }; +/* Value associated with the parse object */ + union acpi_parse_value { u64 integer; /* Integer constant (Up to 64 bits) */ u32 size; /* bytelist or field size */ @@ -1023,6 +1023,31 @@ struct acpi_port_info { #define ACPI_ASCII_ZERO 0x30 +/***************************************************************************** + * + * Disassembler + * + ****************************************************************************/ + +struct acpi_external_list { + char *path; + char *internal_path; + struct acpi_external_list *next; + u32 value; + u16 length; + u8 type; + u8 flags; +}; + +/* Values for Flags field above */ + +#define ACPI_IPATH_ALLOCATED 0x01 + +struct acpi_external_file { + char *path; + struct acpi_external_file *next; +}; + /***************************************************************************** * * Debugger diff --git a/drivers/acpi/acpica/acmacros.h b/drivers/acpi/acpica/acmacros.h index 5efad99f21697597f74882a9d773f5057e3a6618..ed7943b9044f997fbe5b53e3012694bbe1318062 100644 --- a/drivers/acpi/acpica/acmacros.h +++ b/drivers/acpi/acpica/acmacros.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -49,14 +49,18 @@ * get into potential aligment issues -- see the STORE macros below. * Use with care. */ -#define ACPI_GET8(ptr) *ACPI_CAST_PTR (u8, ptr) -#define ACPI_GET16(ptr) *ACPI_CAST_PTR (u16, ptr) -#define ACPI_GET32(ptr) *ACPI_CAST_PTR (u32, ptr) -#define ACPI_GET64(ptr) *ACPI_CAST_PTR (u64, ptr) -#define ACPI_SET8(ptr) *ACPI_CAST_PTR (u8, ptr) -#define ACPI_SET16(ptr) *ACPI_CAST_PTR (u16, ptr) -#define ACPI_SET32(ptr) *ACPI_CAST_PTR (u32, ptr) -#define ACPI_SET64(ptr) *ACPI_CAST_PTR (u64, ptr) +#define ACPI_CAST8(ptr) ACPI_CAST_PTR (u8, (ptr)) +#define ACPI_CAST16(ptr) ACPI_CAST_PTR (u16, (ptr)) +#define ACPI_CAST32(ptr) ACPI_CAST_PTR (u32, (ptr)) +#define ACPI_CAST64(ptr) ACPI_CAST_PTR (u64, (ptr)) +#define ACPI_GET8(ptr) (*ACPI_CAST8 (ptr)) +#define ACPI_GET16(ptr) (*ACPI_CAST16 (ptr)) +#define ACPI_GET32(ptr) (*ACPI_CAST32 (ptr)) +#define ACPI_GET64(ptr) (*ACPI_CAST64 (ptr)) +#define ACPI_SET8(ptr, val) (*ACPI_CAST8 (ptr) = (u8) (val)) +#define ACPI_SET16(ptr, val) (*ACPI_CAST16 (ptr) = (u16) (val)) +#define ACPI_SET32(ptr, val) (*ACPI_CAST32 (ptr) = (u32) (val)) +#define ACPI_SET64(ptr, val) (*ACPI_CAST64 (ptr) = (u64) (val)) /* * printf() format helpers @@ -293,6 +297,26 @@ #define ACPI_16BIT_MASK 0x0000FFFF #define ACPI_24BIT_MASK 0x00FFFFFF +/* Macros to extract flag bits from position zero */ + +#define ACPI_GET_1BIT_FLAG(value) ((value) & ACPI_1BIT_MASK) +#define ACPI_GET_2BIT_FLAG(value) ((value) & ACPI_2BIT_MASK) +#define ACPI_GET_3BIT_FLAG(value) ((value) & ACPI_3BIT_MASK) +#define ACPI_GET_4BIT_FLAG(value) ((value) & ACPI_4BIT_MASK) + +/* Macros to extract flag bits from position one and above */ + +#define ACPI_EXTRACT_1BIT_FLAG(field, position) (ACPI_GET_1BIT_FLAG ((field) >> position)) +#define ACPI_EXTRACT_2BIT_FLAG(field, position) (ACPI_GET_2BIT_FLAG ((field) >> position)) +#define ACPI_EXTRACT_3BIT_FLAG(field, position) (ACPI_GET_3BIT_FLAG ((field) >> position)) +#define ACPI_EXTRACT_4BIT_FLAG(field, position) (ACPI_GET_4BIT_FLAG ((field) >> position)) + +/* ACPI Pathname helpers */ + +#define ACPI_IS_ROOT_PREFIX(c) ((c) == (u8) 0x5C) /* Backslash */ +#define ACPI_IS_PARENT_PREFIX(c) ((c) == (u8) 0x5E) /* Carat */ +#define ACPI_IS_PATH_SEPARATOR(c) ((c) == (u8) 0x2E) /* Period (dot) */ + /* * An object of type struct acpi_namespace_node can appear in some contexts * where a pointer to an object of type union acpi_operand_object can also @@ -364,137 +388,6 @@ #endif /* ACPI_NO_ERROR_MESSAGES */ -/* - * Debug macros that are conditionally compiled - */ -#ifdef ACPI_DEBUG_OUTPUT -/* - * Function entry tracing - */ -#define ACPI_FUNCTION_TRACE(a) ACPI_FUNCTION_NAME(a) \ - acpi_ut_trace(ACPI_DEBUG_PARAMETERS) -#define ACPI_FUNCTION_TRACE_PTR(a, b) ACPI_FUNCTION_NAME(a) \ - acpi_ut_trace_ptr(ACPI_DEBUG_PARAMETERS, (void *)b) -#define ACPI_FUNCTION_TRACE_U32(a, b) ACPI_FUNCTION_NAME(a) \ - acpi_ut_trace_u32(ACPI_DEBUG_PARAMETERS, (u32)b) -#define ACPI_FUNCTION_TRACE_STR(a, b) ACPI_FUNCTION_NAME(a) \ - acpi_ut_trace_str(ACPI_DEBUG_PARAMETERS, (char *)b) - -#define ACPI_FUNCTION_ENTRY() acpi_ut_track_stack_ptr() - -/* - * Function exit tracing. - * WARNING: These macros include a return statement. This is usually considered - * bad form, but having a separate exit macro is very ugly and difficult to maintain. - * One of the FUNCTION_TRACE macros above must be used in conjunction with these macros - * so that "_AcpiFunctionName" is defined. - * - * Note: the DO_WHILE0 macro is used to prevent some compilers from complaining - * about these constructs. - */ -#ifdef ACPI_USE_DO_WHILE_0 -#define ACPI_DO_WHILE0(a) do a while(0) -#else -#define ACPI_DO_WHILE0(a) a -#endif - -#define return_VOID ACPI_DO_WHILE0 ({ \ - acpi_ut_exit (ACPI_DEBUG_PARAMETERS); \ - return;}) -/* - * There are two versions of most of the return macros. The default version is - * safer, since it avoids side-effects by guaranteeing that the argument will - * not be evaluated twice. - * - * A less-safe version of the macros is provided for optional use if the - * compiler uses excessive CPU stack (for example, this may happen in the - * debug case if code optimzation is disabled.) - */ -#ifndef ACPI_SIMPLE_RETURN_MACROS - -#define return_ACPI_STATUS(s) ACPI_DO_WHILE0 ({ \ - register acpi_status _s = (s); \ - acpi_ut_status_exit (ACPI_DEBUG_PARAMETERS, _s); \ - return (_s); }) -#define return_PTR(s) ACPI_DO_WHILE0 ({ \ - register void *_s = (void *) (s); \ - acpi_ut_ptr_exit (ACPI_DEBUG_PARAMETERS, (u8 *) _s); \ - return (_s); }) -#define return_VALUE(s) ACPI_DO_WHILE0 ({ \ - register u64 _s = (s); \ - acpi_ut_value_exit (ACPI_DEBUG_PARAMETERS, _s); \ - return (_s); }) -#define return_UINT8(s) ACPI_DO_WHILE0 ({ \ - register u8 _s = (u8) (s); \ - acpi_ut_value_exit (ACPI_DEBUG_PARAMETERS, (u64) _s); \ - return (_s); }) -#define return_UINT32(s) ACPI_DO_WHILE0 ({ \ - register u32 _s = (u32) (s); \ - acpi_ut_value_exit (ACPI_DEBUG_PARAMETERS, (u64) _s); \ - return (_s); }) -#else /* Use original less-safe macros */ - -#define return_ACPI_STATUS(s) ACPI_DO_WHILE0 ({ \ - acpi_ut_status_exit (ACPI_DEBUG_PARAMETERS, (s)); \ - return((s)); }) -#define return_PTR(s) ACPI_DO_WHILE0 ({ \ - acpi_ut_ptr_exit (ACPI_DEBUG_PARAMETERS, (u8 *) (s)); \ - return((s)); }) -#define return_VALUE(s) ACPI_DO_WHILE0 ({ \ - acpi_ut_value_exit (ACPI_DEBUG_PARAMETERS, (u64) (s)); \ - return((s)); }) -#define return_UINT8(s) return_VALUE(s) -#define return_UINT32(s) return_VALUE(s) - -#endif /* ACPI_SIMPLE_RETURN_MACROS */ - -/* Conditional execution */ - -#define ACPI_DEBUG_EXEC(a) a -#define ACPI_DEBUG_ONLY_MEMBERS(a) a; -#define _VERBOSE_STRUCTURES - -/* Various object display routines for debug */ - -#define ACPI_DUMP_STACK_ENTRY(a) acpi_ex_dump_operand((a), 0) -#define ACPI_DUMP_OPERANDS(a, b ,c) acpi_ex_dump_operands(a, b, c) -#define ACPI_DUMP_ENTRY(a, b) acpi_ns_dump_entry (a, b) -#define ACPI_DUMP_PATHNAME(a, b, c, d) acpi_ns_dump_pathname(a, b, c, d) -#define ACPI_DUMP_BUFFER(a, b) acpi_ut_debug_dump_buffer((u8 *) a, b, DB_BYTE_DISPLAY, _COMPONENT) - -#else -/* - * This is the non-debug case -- make everything go away, - * leaving no executable debug code! - */ -#define ACPI_DEBUG_EXEC(a) -#define ACPI_DEBUG_ONLY_MEMBERS(a) -#define ACPI_FUNCTION_TRACE(a) -#define ACPI_FUNCTION_TRACE_PTR(a, b) -#define ACPI_FUNCTION_TRACE_U32(a, b) -#define ACPI_FUNCTION_TRACE_STR(a, b) -#define ACPI_FUNCTION_EXIT -#define ACPI_FUNCTION_STATUS_EXIT(s) -#define ACPI_FUNCTION_VALUE_EXIT(s) -#define ACPI_FUNCTION_ENTRY() -#define ACPI_DUMP_STACK_ENTRY(a) -#define ACPI_DUMP_OPERANDS(a, b, c) -#define ACPI_DUMP_ENTRY(a, b) -#define ACPI_DUMP_TABLES(a, b) -#define ACPI_DUMP_PATHNAME(a, b, c, d) -#define ACPI_DUMP_BUFFER(a, b) -#define ACPI_DEBUG_PRINT(pl) -#define ACPI_DEBUG_PRINT_RAW(pl) - -#define return_VOID return -#define return_ACPI_STATUS(s) return(s) -#define return_VALUE(s) return(s) -#define return_UINT8(s) return(s) -#define return_UINT32(s) return(s) -#define return_PTR(s) return(s) - -#endif /* ACPI_DEBUG_OUTPUT */ - #if (!ACPI_REDUCED_HARDWARE) #define ACPI_HW_OPTIONAL_FUNCTION(addr) addr #else diff --git a/drivers/acpi/acpica/acnamesp.h b/drivers/acpi/acpica/acnamesp.h index 9b19d4b8642407ee8650a988bbb31d653652c787..02cd5482ff8b2faddf380efb5a3df96c53a75ce6 100644 --- a/drivers/acpi/acpica/acnamesp.h +++ b/drivers/acpi/acpica/acnamesp.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -218,6 +218,18 @@ acpi_ns_check_parameter_count(char *pathname, u32 user_param_count, const union acpi_predefined_info *info); +acpi_status +acpi_ns_check_object_type(struct acpi_predefined_data *data, + union acpi_operand_object **return_object_ptr, + u32 expected_btypes, u32 package_index); + +/* + * nsprepkg - Validation of predefined name packages + */ +acpi_status +acpi_ns_check_package(struct acpi_predefined_data *data, + union acpi_operand_object **return_object_ptr); + /* * nsnames - Name and Scope manipulation */ @@ -333,8 +345,6 @@ acpi_ns_install_node(struct acpi_walk_state *walk_state, /* * nsutils - Utility functions */ -u8 acpi_ns_valid_root_prefix(char prefix); - acpi_object_type acpi_ns_get_type(struct acpi_namespace_node *node); u32 acpi_ns_local(acpi_object_type type); diff --git a/drivers/acpi/acpica/acobject.h b/drivers/acpi/acpica/acobject.h index 24eb9eac95145bc9e47e33efb1a42b97bd4066f5..cc7ab6dd724e6234a835d0321c8cb4b6106796f4 100644 --- a/drivers/acpi/acpica/acobject.h +++ b/drivers/acpi/acpica/acobject.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -307,7 +307,7 @@ struct acpi_object_addr_handler { struct acpi_namespace_node *node; /* Parent device */ void *context; acpi_adr_space_setup setup; - union acpi_operand_object *region_list; /* regions using this handler */ + union acpi_operand_object *region_list; /* Regions using this handler */ union acpi_operand_object *next; }; diff --git a/drivers/acpi/acpica/acopcode.h b/drivers/acpi/acpica/acopcode.h index d786a5128b784813b65501bdb113bb08a1c2e09d..3fc9ca7e8aa3e6afee0933d1ac82efe33c8ba04d 100644 --- a/drivers/acpi/acpica/acopcode.h +++ b/drivers/acpi/acpica/acopcode.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/acparser.h b/drivers/acpi/acpica/acparser.h index eefcf47a61a0478072c297f564715c7f0bdabb8c..aed319318835f3c9b47a53acbb9618da37629c83 100644 --- a/drivers/acpi/acpica/acparser.h +++ b/drivers/acpi/acpica/acparser.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -105,7 +105,28 @@ union acpi_parse_object *acpi_ps_find_name(union acpi_parse_object *scope, union acpi_parse_object *acpi_ps_get_parent(union acpi_parse_object *op); /* - * psopcode - AML Opcode information + * psobject - support for parse object processing + */ +acpi_status +acpi_ps_build_named_op(struct acpi_walk_state *walk_state, + u8 *aml_op_start, + union acpi_parse_object *unnamed_op, + union acpi_parse_object **op); + +acpi_status +acpi_ps_create_op(struct acpi_walk_state *walk_state, + u8 *aml_op_start, union acpi_parse_object **new_op); + +acpi_status +acpi_ps_complete_op(struct acpi_walk_state *walk_state, + union acpi_parse_object **op, acpi_status status); + +acpi_status +acpi_ps_complete_final_op(struct acpi_walk_state *walk_state, + union acpi_parse_object *op, acpi_status status); + +/* + * psopinfo - AML Opcode information */ const struct acpi_opcode_info *acpi_ps_get_opcode_info(u16 opcode); @@ -211,8 +232,6 @@ void acpi_ps_free_op(union acpi_parse_object *op); u8 acpi_ps_is_leading_char(u32 c); -u8 acpi_ps_is_prefix_char(u32 c); - #ifdef ACPI_FUTURE_USAGE u32 acpi_ps_get_name(union acpi_parse_object *op); #endif /* ACPI_FUTURE_USAGE */ diff --git a/drivers/acpi/acpica/acpredef.h b/drivers/acpi/acpica/acpredef.h index 9dfa1c83bd4e4812c6f4322f1a7ea89a60bcf82c..752cc40cdc1e1f449e12410cf38a0dc7e9ecf259 100644 --- a/drivers/acpi/acpica/acpredef.h +++ b/drivers/acpi/acpica/acpredef.h @@ -1,12 +1,11 @@ /****************************************************************************** * * Name: acpredef - Information table for ACPI predefined methods and objects - * $Revision: 1.1 $ * *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -51,13 +50,13 @@ * * 1) PTYPE1 packages do not contain sub-packages. * - * ACPI_PTYPE1_FIXED: Fixed length, 1 or 2 object types: + * ACPI_PTYPE1_FIXED: Fixed-length length, 1 or 2 object types: * object type * count * object type * count * - * ACPI_PTYPE1_VAR: Variable length: + * ACPI_PTYPE1_VAR: Variable-length length: * object type (Int/Buf/Ref) * * ACPI_PTYPE1_OPTION: Package has some required and some optional elements @@ -85,10 +84,10 @@ * count * (Used for _CST) * - * ACPI_PTYPE2_FIXED: Each subpackage is of fixed length + * ACPI_PTYPE2_FIXED: Each subpackage is of Fixed-length * (Used for _PRT) * - * ACPI_PTYPE2_MIN: Each subpackage has a variable but minimum length + * ACPI_PTYPE2_MIN: Each subpackage has a Variable-length but minimum length * (Used for _HPX) * * ACPI_PTYPE2_REV_FIXED: Revision at start, each subpackage is Fixed-length @@ -124,7 +123,8 @@ enum acpi_return_package_types { * These are the names that can actually be evaluated via acpi_evaluate_object. * Not present in this table are the following: * - * 1) Predefined/Reserved names that are never evaluated via acpi_evaluate_object: + * 1) Predefined/Reserved names that are never evaluated via + * acpi_evaluate_object: * _Lxx and _Exx GPE methods * _Qxx EC methods * _T_x compiler temporary variables @@ -149,6 +149,8 @@ enum acpi_return_package_types { * information about the expected structure of the package. This information * is saved here (rather than in a separate table) in order to minimize the * overall size of the stored data. + * + * Note: The additional braces are intended to promote portability. */ static const union acpi_predefined_info predefined_names[] = { {{"_AC0", 0, ACPI_RTYPE_INTEGER}}, @@ -212,9 +214,8 @@ static const union acpi_predefined_info predefined_names[] = { {{"_BCT", 1, ACPI_RTYPE_INTEGER}}, {{"_BDN", 0, ACPI_RTYPE_INTEGER}}, {{"_BFS", 1, 0}}, - {{"_BIF", 0, ACPI_RTYPE_PACKAGE} }, /* Fixed-length (9 Int),(4 Str/Buf) */ - {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 9, - ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER}, 4, 0} }, + {{"_BIF", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (9 Int),(4 Str) */ + {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 9, ACPI_RTYPE_STRING}, 4, 0}}, {{"_BIX", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (16 Int),(4 Str) */ {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 16, ACPI_RTYPE_STRING}, 4, @@ -236,7 +237,8 @@ static const union acpi_predefined_info predefined_names[] = { {{"_CBA", 0, ACPI_RTYPE_INTEGER}}, /* See PCI firmware spec 3.0 */ {{"_CDM", 0, ACPI_RTYPE_INTEGER}}, {{"_CID", 0, ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_PACKAGE}}, /* Variable-length (Ints/Strs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING, 0,0}, 0,0}}, + {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING, 0, 0}, 0, + 0}}, {{"_CLS", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (3 Int) */ {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 3, 0}, 0, 0}}, @@ -251,7 +253,8 @@ static const union acpi_predefined_info predefined_names[] = { {{{ACPI_PTYPE2_COUNT, ACPI_RTYPE_INTEGER, 0,0}, 0,0}}, {{"_CST", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (1 Int(n), n Pkg (1 Buf/3 Int) */ - {{{ACPI_PTYPE2_PKG_COUNT,ACPI_RTYPE_BUFFER, 1, ACPI_RTYPE_INTEGER}, 3,0}}, + {{{ACPI_PTYPE2_PKG_COUNT, ACPI_RTYPE_BUFFER, 1, ACPI_RTYPE_INTEGER}, 3, + 0}}, {{"_CWS", 1, ACPI_RTYPE_INTEGER}}, {{"_DCK", 1, ACPI_RTYPE_INTEGER}}, @@ -342,8 +345,8 @@ static const union acpi_predefined_info predefined_names[] = { {{"_MBM", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (8 Int) */ {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 8, 0}, 0, 0}}, - {{"_MLS", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each (2 Str) */ - {{{ACPI_PTYPE2, ACPI_RTYPE_STRING, 2,0}, 0,0}}, + {{"_MLS", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each (1 Str/1 Buf) */ + {{{ACPI_PTYPE2, ACPI_RTYPE_STRING, 1, ACPI_RTYPE_BUFFER}, 1, 0}}, {{"_MSG", 1, 0}}, {{"_MSM", 4, ACPI_RTYPE_INTEGER}}, diff --git a/drivers/acpi/acpica/acresrc.h b/drivers/acpi/acpica/acresrc.h index 0347d099349708a6f21035467ac96e2eb5578105..f691d0e4d9fa091faeb0ebc231e8701b399c264b 100644 --- a/drivers/acpi/acpica/acresrc.h +++ b/drivers/acpi/acpica/acresrc.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -347,18 +347,21 @@ extern struct acpi_rsdump_info *acpi_gbl_dump_resource_dispatch[]; extern struct acpi_rsdump_info *acpi_gbl_dump_serial_bus_dispatch[]; /* - * rsdump + * rsdumpinfo */ extern struct acpi_rsdump_info acpi_rs_dump_irq[]; +extern struct acpi_rsdump_info acpi_rs_dump_prt[]; extern struct acpi_rsdump_info acpi_rs_dump_dma[]; extern struct acpi_rsdump_info acpi_rs_dump_start_dpf[]; extern struct acpi_rsdump_info acpi_rs_dump_end_dpf[]; extern struct acpi_rsdump_info acpi_rs_dump_io[]; +extern struct acpi_rsdump_info acpi_rs_dump_io_flags[]; extern struct acpi_rsdump_info acpi_rs_dump_fixed_io[]; extern struct acpi_rsdump_info acpi_rs_dump_vendor[]; extern struct acpi_rsdump_info acpi_rs_dump_end_tag[]; extern struct acpi_rsdump_info acpi_rs_dump_memory24[]; extern struct acpi_rsdump_info acpi_rs_dump_memory32[]; +extern struct acpi_rsdump_info acpi_rs_dump_memory_flags[]; extern struct acpi_rsdump_info acpi_rs_dump_fixed_memory32[]; extern struct acpi_rsdump_info acpi_rs_dump_address16[]; extern struct acpi_rsdump_info acpi_rs_dump_address32[]; @@ -372,6 +375,7 @@ extern struct acpi_rsdump_info acpi_rs_dump_common_serial_bus[]; extern struct acpi_rsdump_info acpi_rs_dump_i2c_serial_bus[]; extern struct acpi_rsdump_info acpi_rs_dump_spi_serial_bus[]; extern struct acpi_rsdump_info acpi_rs_dump_uart_serial_bus[]; +extern struct acpi_rsdump_info acpi_rs_dump_general_flags[]; #endif #endif /* __ACRESRC_H__ */ diff --git a/drivers/acpi/acpica/acstruct.h b/drivers/acpi/acpica/acstruct.h index 937e66c65d1e2ddf541b373280f00a36b3bb90ef..7896d85876cacd534991bf72e4a920ce041947b8 100644 --- a/drivers/acpi/acpica/acstruct.h +++ b/drivers/acpi/acpica/acstruct.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/actables.h b/drivers/acpi/acpica/actables.h index 6712965ba8ae68f35aad59b36b2ae7570371f644..7755e915a007a9aec4ecefce08f2bfdceb7b2a7f 100644 --- a/drivers/acpi/acpica/actables.h +++ b/drivers/acpi/acpica/actables.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h index b0f5f92b674aa40e7ec54af59de76aca354d309d..0082fa0a613976ce74dc271eb6ade9f157c3fba8 100644 --- a/drivers/acpi/acpica/acutils.h +++ b/drivers/acpi/acpica/acutils.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -483,39 +483,17 @@ acpi_ut_short_divide(u64 in_dividend, /* * utmisc */ -void ut_convert_backslashes(char *pathname); - const char *acpi_ut_validate_exception(acpi_status status); u8 acpi_ut_is_pci_root_bridge(char *id); u8 acpi_ut_is_aml_table(struct acpi_table_header *table); -acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id); - -void acpi_ut_release_owner_id(acpi_owner_id * owner_id); - acpi_status acpi_ut_walk_package_tree(union acpi_operand_object *source_object, void *target_object, acpi_pkg_callback walk_callback, void *context); -void acpi_ut_strupr(char *src_string); - -void acpi_ut_strlwr(char *src_string); - -int acpi_ut_stricmp(char *string1, char *string2); - -void acpi_ut_print_string(char *string, u8 max_length); - -u8 acpi_ut_valid_acpi_name(u32 name); - -void acpi_ut_repair_name(char *name); - -u8 acpi_ut_valid_acpi_char(char character, u32 position); - -acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer); - /* Values for Base above (16=Hex, 10=Decimal) */ #define ACPI_ANY_BASE 0 @@ -531,16 +509,26 @@ acpi_ut_display_init_pathname(u8 type, char *path); #endif +/* + * utownerid - Support for Table/Method Owner IDs + */ +acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id); + +void acpi_ut_release_owner_id(acpi_owner_id * owner_id); + /* * utresrc */ acpi_status -acpi_ut_walk_aml_resources(u8 *aml, +acpi_ut_walk_aml_resources(struct acpi_walk_state *walk_state, + u8 *aml, acpi_size aml_length, acpi_walk_aml_callback user_function, void **context); -acpi_status acpi_ut_validate_resource(void *aml, u8 *return_index); +acpi_status +acpi_ut_validate_resource(struct acpi_walk_state *walk_state, + void *aml, u8 *return_index); u32 acpi_ut_get_descriptor_length(void *aml); @@ -553,6 +541,27 @@ u8 acpi_ut_get_resource_type(void *aml); acpi_status acpi_ut_get_resource_end_tag(union acpi_operand_object *obj_desc, u8 **end_tag); +/* + * utstring - String and character utilities + */ +void acpi_ut_strupr(char *src_string); + +void acpi_ut_strlwr(char *src_string); + +int acpi_ut_stricmp(char *string1, char *string2); + +acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer); + +void acpi_ut_print_string(char *string, u8 max_length); + +void ut_convert_backslashes(char *pathname); + +u8 acpi_ut_valid_acpi_name(u32 name); + +u8 acpi_ut_valid_acpi_char(char character, u32 position); + +void acpi_ut_repair_name(char *name); + /* * utmutex - mutex support */ diff --git a/drivers/acpi/acpica/amlcode.h b/drivers/acpi/acpica/amlcode.h index c26f8ff6c3b995922e71c15369c30e1d5de1be55..48a3e331b72d7e7c8214969217d4e57e3c535d3e 100644 --- a/drivers/acpi/acpica/amlcode.h +++ b/drivers/acpi/acpica/amlcode.h @@ -7,7 +7,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/amlresrc.h b/drivers/acpi/acpica/amlresrc.h index 968449685e06c28b8cb5a22687eb90d1e2c0fc0f..87c26366d1dfa8a9e65d8931f067d28330d8aa57 100644 --- a/drivers/acpi/acpica/amlresrc.h +++ b/drivers/acpi/acpica/amlresrc.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -199,6 +199,12 @@ struct aml_resource_fixed_dma { struct aml_resource_large_header { AML_RESOURCE_LARGE_HEADER_COMMON}; +/* General Flags for address space resource descriptors */ + +#define ACPI_RESOURCE_FLAG_DEC 2 +#define ACPI_RESOURCE_FLAG_MIF 4 +#define ACPI_RESOURCE_FLAG_MAF 8 + struct aml_resource_memory24 { AML_RESOURCE_LARGE_HEADER_COMMON u8 flags; u16 minimum; diff --git a/drivers/acpi/acpica/dsargs.c b/drivers/acpi/acpica/dsargs.c index c8b5e2565b987164a2f42138b521b7bfb90798fc..fb09b08d7080100b250fbf6ffa164bda1ad43b55 100644 --- a/drivers/acpi/acpica/dsargs.c +++ b/drivers/acpi/acpica/dsargs.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dscontrol.c b/drivers/acpi/acpica/dscontrol.c index 57895db3231ae8d5ee6c8591bd749f2ae010adf6..7ea0f162f11ca42e11d7247fc3263d4c1fb0b2e1 100644 --- a/drivers/acpi/acpica/dscontrol.c +++ b/drivers/acpi/acpica/dscontrol.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dsfield.c b/drivers/acpi/acpica/dsfield.c index b5b904ee815f7653c097d9b8b3d1ed010b2d4311..feadeed1012dc2256c1596bb79e7ff6190e6cb41 100644 --- a/drivers/acpi/acpica/dsfield.c +++ b/drivers/acpi/acpica/dsfield.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dsinit.c b/drivers/acpi/acpica/dsinit.c index 87eff701ecfae63c066a88c0adb944133a9079af..bc8e63f7784b96a7bf39c5476dc9cacd07688bb5 100644 --- a/drivers/acpi/acpica/dsinit.c +++ b/drivers/acpi/acpica/dsinit.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dsmethod.c b/drivers/acpi/acpica/dsmethod.c index 52eb4e01622aebd52d8abbf16d67e02fa617f55b..a9ffd44c18fe322b0a73b97bbe5c11207464c1ba 100644 --- a/drivers/acpi/acpica/dsmethod.c +++ b/drivers/acpi/acpica/dsmethod.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -47,7 +47,7 @@ #include "acinterp.h" #include "acnamesp.h" #ifdef ACPI_DISASSEMBLER -#include +#include "acdisasm.h" #endif #define _COMPONENT ACPI_DISPATCHER @@ -151,6 +151,7 @@ acpi_ds_create_method_mutex(union acpi_operand_object *method_desc) status = acpi_os_create_mutex(&mutex_desc->mutex.os_mutex); if (ACPI_FAILURE(status)) { + acpi_ut_delete_object_desc(mutex_desc); return_ACPI_STATUS(status); } @@ -378,7 +379,8 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread, */ info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); if (!info) { - return_ACPI_STATUS(AE_NO_MEMORY); + status = AE_NO_MEMORY; + goto cleanup; } info->parameters = &this_walk_state->operands[0]; diff --git a/drivers/acpi/acpica/dsmthdat.c b/drivers/acpi/acpica/dsmthdat.c index 9a83b7e0f3bac714c48c0486c9d4d6f8219ac2e9..3da80460ce38af069241fb59ee41d2aeb695d319 100644 --- a/drivers/acpi/acpica/dsmthdat.c +++ b/drivers/acpi/acpica/dsmthdat.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dsobject.c b/drivers/acpi/acpica/dsobject.c index c9f15d3a368614dcf0fa338212f8c068725bb387..e20e9f84eee80653b6dfc932f140c6eaebf4a5ac 100644 --- a/drivers/acpi/acpica/dsobject.c +++ b/drivers/acpi/acpica/dsobject.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -388,7 +388,7 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, union acpi_parse_object *parent; union acpi_operand_object *obj_desc = NULL; acpi_status status = AE_OK; - unsigned i; + u32 i; u16 index; u16 reference_count; @@ -525,7 +525,7 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, } ACPI_INFO((AE_INFO, - "Actual Package length (%u) is larger than NumElements field (%u), truncated\n", + "Actual Package length (%u) is larger than NumElements field (%u), truncated", i, element_count)); } else if (i < element_count) { /* @@ -703,7 +703,7 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state, /* Truncate value if we are executing from a 32-bit ACPI table */ #ifndef ACPI_NO_METHOD_EXECUTION - acpi_ex_truncate_for32bit_table(obj_desc); + (void)acpi_ex_truncate_for32bit_table(obj_desc); #endif break; @@ -725,8 +725,18 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state, case AML_TYPE_LITERAL: obj_desc->integer.value = op->common.value.integer; + #ifndef ACPI_NO_METHOD_EXECUTION - acpi_ex_truncate_for32bit_table(obj_desc); + if (acpi_ex_truncate_for32bit_table(obj_desc)) { + + /* Warn if we found a 64-bit constant in a 32-bit table */ + + ACPI_WARNING((AE_INFO, + "Truncated 64-bit constant found in 32-bit table: %8.8X%8.8X => %8.8X", + ACPI_FORMAT_UINT64(op->common. + value.integer), + (u32)obj_desc->integer.value)); + } #endif break; diff --git a/drivers/acpi/acpica/dsopcode.c b/drivers/acpi/acpica/dsopcode.c index d09c6b4bab2c9632cf2bfa88ea5fb8ed196e10d4..ee6367b8eaf7afcf6866ff75193e5ca59bfa94f4 100644 --- a/drivers/acpi/acpica/dsopcode.c +++ b/drivers/acpi/acpica/dsopcode.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -486,18 +486,18 @@ acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state, ACPI_FUNCTION_TRACE_PTR(ds_eval_table_region_operands, op); /* - * This is where we evaluate the signature_string and oem_iDString - * and oem_table_iDString of the data_table_region declaration + * This is where we evaluate the Signature string, oem_id string, + * and oem_table_id string of the Data Table Region declaration */ node = op->common.node; - /* next_op points to signature_string op */ + /* next_op points to Signature string op */ next_op = op->common.value.arg; /* - * Evaluate/create the signature_string and oem_iDString - * and oem_table_iDString operands + * Evaluate/create the Signature string, oem_id string, + * and oem_table_id string operands */ status = acpi_ds_create_operands(walk_state, next_op); if (ACPI_FAILURE(status)) { @@ -505,8 +505,8 @@ acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state, } /* - * Resolve the signature_string and oem_iDString - * and oem_table_iDString operands + * Resolve the Signature string, oem_id string, + * and oem_table_id string operands */ status = acpi_ex_resolve_operands(op->common.aml_opcode, ACPI_WALK_OPERANDS, walk_state); diff --git a/drivers/acpi/acpica/dsutils.c b/drivers/acpi/acpica/dsutils.c index afeb99f494827a66c0a72d201962dbcd0189fe22..4d8c992a51d83e4bcd04c6a2556afaa25f7400c8 100644 --- a/drivers/acpi/acpica/dsutils.c +++ b/drivers/acpi/acpica/dsutils.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -178,7 +178,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op, if (!op) { ACPI_ERROR((AE_INFO, "Null Op")); - return_UINT8(TRUE); + return_VALUE(TRUE); } /* @@ -210,7 +210,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op, "At Method level, result of [%s] not used\n", acpi_ps_get_opcode_name(op->common. aml_opcode))); - return_UINT8(FALSE); + return_VALUE(FALSE); } /* Get info on the parent. The root_op is AML_SCOPE */ @@ -219,7 +219,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op, acpi_ps_get_opcode_info(op->common.parent->common.aml_opcode); if (parent_info->class == AML_CLASS_UNKNOWN) { ACPI_ERROR((AE_INFO, "Unknown parent opcode Op=%p", op)); - return_UINT8(FALSE); + return_VALUE(FALSE); } /* @@ -307,7 +307,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op, acpi_ps_get_opcode_name(op->common.parent->common. aml_opcode), op)); - return_UINT8(TRUE); + return_VALUE(TRUE); result_not_used: ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, @@ -316,7 +316,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op, acpi_ps_get_opcode_name(op->common.parent->common. aml_opcode), op)); - return_UINT8(FALSE); + return_VALUE(FALSE); } /******************************************************************************* diff --git a/drivers/acpi/acpica/dswexec.c b/drivers/acpi/acpica/dswexec.c index 58593931be96bfa925cd6f14eacc836471599cec..44f8325c2bae0e0c8b67d11e4f29966b6e700fb0 100644 --- a/drivers/acpi/acpica/dswexec.c +++ b/drivers/acpi/acpica/dswexec.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -149,7 +149,7 @@ acpi_ds_get_predicate_value(struct acpi_walk_state *walk_state, /* Truncate the predicate to 32-bits if necessary */ - acpi_ex_truncate_for32bit_table(local_obj_desc); + (void)acpi_ex_truncate_for32bit_table(local_obj_desc); /* * Save the result of the predicate evaluation on @@ -706,7 +706,7 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) * ACPI 2.0 support for 64-bit integers: Truncate numeric * result value if we are executing from a 32-bit ACPI table */ - acpi_ex_truncate_for32bit_table(walk_state->result_obj); + (void)acpi_ex_truncate_for32bit_table(walk_state->result_obj); /* * Check if we just completed the evaluation of a diff --git a/drivers/acpi/acpica/dswload.c b/drivers/acpi/acpica/dswload.c index 557510084c7aca459fb24ace485dd89c98aa26bc..6e17c0e24e63ca4e758d1e2a2147419ed5e4b0ec 100644 --- a/drivers/acpi/acpica/dswload.c +++ b/drivers/acpi/acpica/dswload.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -50,7 +50,7 @@ #include "acnamesp.h" #ifdef ACPI_ASL_COMPILER -#include +#include "acdisasm.h" #endif #define _COMPONENT ACPI_DISPATCHER @@ -178,7 +178,8 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, * Target of Scope() not found. Generate an External for it, and * insert the name into the namespace. */ - acpi_dm_add_to_external_list(path, ACPI_TYPE_DEVICE, 0); + acpi_dm_add_to_external_list(op, path, ACPI_TYPE_DEVICE, + 0); status = acpi_ns_lookup(walk_state->scope_info, path, object_type, ACPI_IMODE_LOAD_PASS1, diff --git a/drivers/acpi/acpica/dswload2.c b/drivers/acpi/acpica/dswload2.c index 3798357483578d9569cc004d1e05ff5d3ff905a7..4407ff2377d5918b10fe08875434ed07b981d836 100644 --- a/drivers/acpi/acpica/dswload2.c +++ b/drivers/acpi/acpica/dswload2.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -222,7 +222,7 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, */ ACPI_WARNING((AE_INFO, "Type override - [%4.4s] had invalid type (%s) " - "for Scope operator, changed to type ANY\n", + "for Scope operator, changed to type ANY", acpi_ut_get_node_name(node), acpi_ut_get_type_name(node->type))); diff --git a/drivers/acpi/acpica/dswscope.c b/drivers/acpi/acpica/dswscope.c index f6c4295470ae9117226d0031c763c619248fe4eb..d67891de1b545b43f33dca806d784dda884cfedb 100644 --- a/drivers/acpi/acpica/dswscope.c +++ b/drivers/acpi/acpica/dswscope.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dswstate.c b/drivers/acpi/acpica/dswstate.c index 3e65a15a735fd1ecce0ca94b3feed176b7fd868b..ecb12e2137ffb4ff736541891122afcf145b4f61 100644 --- a/drivers/acpi/acpica/dswstate.c +++ b/drivers/acpi/acpica/dswstate.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/evevent.c b/drivers/acpi/acpica/evevent.c index d4acfbbe5b2947624b89d5cf651a759256c89ded..b8ea0b26cde33aea6a78f34a10e379d79a7d60fc 100644 --- a/drivers/acpi/acpica/evevent.c +++ b/drivers/acpi/acpica/evevent.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/evglock.c b/drivers/acpi/acpica/evglock.c index af14a71376329bdd7aa7558da4bc69121726bb79..a621481c6cf27f946a6050f5ef9f6ea466b51689 100644 --- a/drivers/acpi/acpica/evglock.c +++ b/drivers/acpi/acpica/evglock.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c index 36d1205744238a092ab686324d030690f120533f..b9adb9a7ed8550ba2702b38e69929d1fa84e6062 100644 --- a/drivers/acpi/acpica/evgpe.c +++ b/drivers/acpi/acpica/evgpe.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -561,8 +561,8 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) status = AE_NO_MEMORY; } else { /* - * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the _Lxx/_Exx - * control method that corresponds to this GPE + * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the + * _Lxx/_Exx control method that corresponds to this GPE */ info->prefix_node = local_gpe_event_info->dispatch.method_node; @@ -707,7 +707,7 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device, if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Unable to clear GPE%02X", gpe_number)); - return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); + return_VALUE(ACPI_INTERRUPT_NOT_HANDLED); } } @@ -724,7 +724,7 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device, if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Unable to disable GPE%02X", gpe_number)); - return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); + return_VALUE(ACPI_INTERRUPT_NOT_HANDLED); } /* @@ -765,7 +765,7 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device, gpe_event_info); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, - "Unable to queue handler for GPE%2X - event disabled", + "Unable to queue handler for GPE%02X - event disabled", gpe_number)); } break; @@ -784,7 +784,7 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device, break; } - return_UINT32(ACPI_INTERRUPT_HANDLED); + return_VALUE(ACPI_INTERRUPT_HANDLED); } #endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/drivers/acpi/acpica/evgpeblk.c b/drivers/acpi/acpica/evgpeblk.c index 1571a61a78335c4520a178571e41bc847d234290..a2d688bbac02c7ee96e43b5764f97442c1dd2a6f 100644 --- a/drivers/acpi/acpica/evgpeblk.c +++ b/drivers/acpi/acpica/evgpeblk.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -405,13 +405,13 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device, (*return_gpe_block) = gpe_block; } - ACPI_DEBUG_PRINT((ACPI_DB_INIT, - "GPE %02X to %02X [%4.4s] %u regs on int 0x%X\n", - (u32) gpe_block->block_base_number, - (u32) (gpe_block->block_base_number + - (gpe_block->gpe_count - 1)), - gpe_device->name.ascii, gpe_block->register_count, - interrupt_number)); + ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, + " Initialized GPE %02X to %02X [%4.4s] %u regs on interrupt 0x%X\n", + (u32)gpe_block->block_base_number, + (u32)(gpe_block->block_base_number + + (gpe_block->gpe_count - 1)), + gpe_device->name.ascii, gpe_block->register_count, + interrupt_number)); /* Update global count of currently available GPEs */ @@ -496,9 +496,11 @@ acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, } if (gpe_enabled_count) { - ACPI_DEBUG_PRINT((ACPI_DB_INIT, - "Enabled %u GPEs in this block\n", - gpe_enabled_count)); + ACPI_INFO((AE_INFO, + "Enabled %u GPEs in block %02X to %02X", + gpe_enabled_count, (u32)gpe_block->block_base_number, + (u32)(gpe_block->block_base_number + + (gpe_block->gpe_count - 1)))); } gpe_block->initialized = TRUE; diff --git a/drivers/acpi/acpica/evgpeinit.c b/drivers/acpi/acpica/evgpeinit.c index da0add858f813ff2c2d5e9d9f45adb78794fabc0..72b8f6b3f4cafeac10eee0bacfa2af5c1851f281 100644 --- a/drivers/acpi/acpica/evgpeinit.c +++ b/drivers/acpi/acpica/evgpeinit.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -86,6 +86,9 @@ acpi_status acpi_ev_gpe_initialize(void) ACPI_FUNCTION_TRACE(ev_gpe_initialize); + ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, + "Initializing General Purpose Events (GPEs):\n")); + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); diff --git a/drivers/acpi/acpica/evgpeutil.c b/drivers/acpi/acpica/evgpeutil.c index 228a0c3b1d49db65c1d27df0225586038c790d90..b24dbb80fab8f681dc3089cd8a29c700f5cb57c7 100644 --- a/drivers/acpi/acpica/evgpeutil.c +++ b/drivers/acpi/acpica/evgpeutil.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/evhandler.c b/drivers/acpi/acpica/evhandler.c new file mode 100644 index 0000000000000000000000000000000000000000..d4f83112c2e266ff2fcf5f8415d9714ffa071330 --- /dev/null +++ b/drivers/acpi/acpica/evhandler.c @@ -0,0 +1,529 @@ +/****************************************************************************** + * + * Module Name: evhandler - Support for Address Space handlers + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2013, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include "accommon.h" +#include "acevents.h" +#include "acnamesp.h" +#include "acinterp.h" + +#define _COMPONENT ACPI_EVENTS +ACPI_MODULE_NAME("evhandler") + +/* Local prototypes */ +static acpi_status +acpi_ev_install_handler(acpi_handle obj_handle, + u32 level, void *context, void **return_value); + +/* These are the address spaces that will get default handlers */ + +u8 acpi_gbl_default_address_spaces[ACPI_NUM_DEFAULT_SPACES] = { + ACPI_ADR_SPACE_SYSTEM_MEMORY, + ACPI_ADR_SPACE_SYSTEM_IO, + ACPI_ADR_SPACE_PCI_CONFIG, + ACPI_ADR_SPACE_DATA_TABLE +}; + +/******************************************************************************* + * + * FUNCTION: acpi_ev_install_region_handlers + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Installs the core subsystem default address space handlers. + * + ******************************************************************************/ + +acpi_status acpi_ev_install_region_handlers(void) +{ + acpi_status status; + u32 i; + + ACPI_FUNCTION_TRACE(ev_install_region_handlers); + + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * All address spaces (PCI Config, EC, SMBus) are scope dependent and + * registration must occur for a specific device. + * + * In the case of the system memory and IO address spaces there is + * currently no device associated with the address space. For these we + * use the root. + * + * We install the default PCI config space handler at the root so that + * this space is immediately available even though the we have not + * enumerated all the PCI Root Buses yet. This is to conform to the ACPI + * specification which states that the PCI config space must be always + * available -- even though we are nowhere near ready to find the PCI root + * buses at this point. + * + * NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler + * has already been installed (via acpi_install_address_space_handler). + * Similar for AE_SAME_HANDLER. + */ + for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) { + status = acpi_ev_install_space_handler(acpi_gbl_root_node, + acpi_gbl_default_address_spaces + [i], + ACPI_DEFAULT_HANDLER, + NULL, NULL); + switch (status) { + case AE_OK: + case AE_SAME_HANDLER: + case AE_ALREADY_EXISTS: + + /* These exceptions are all OK */ + + status = AE_OK; + break; + + default: + + goto unlock_and_exit; + } + } + + unlock_and_exit: + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_has_default_handler + * + * PARAMETERS: node - Namespace node for the device + * space_id - The address space ID + * + * RETURN: TRUE if default handler is installed, FALSE otherwise + * + * DESCRIPTION: Check if the default handler is installed for the requested + * space ID. + * + ******************************************************************************/ + +u8 +acpi_ev_has_default_handler(struct acpi_namespace_node *node, + acpi_adr_space_type space_id) +{ + union acpi_operand_object *obj_desc; + union acpi_operand_object *handler_obj; + + /* Must have an existing internal object */ + + obj_desc = acpi_ns_get_attached_object(node); + if (obj_desc) { + handler_obj = obj_desc->device.handler; + + /* Walk the linked list of handlers for this object */ + + while (handler_obj) { + if (handler_obj->address_space.space_id == space_id) { + if (handler_obj->address_space.handler_flags & + ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) { + return (TRUE); + } + } + + handler_obj = handler_obj->address_space.next; + } + } + + return (FALSE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_install_handler + * + * PARAMETERS: walk_namespace callback + * + * DESCRIPTION: This routine installs an address handler into objects that are + * of type Region or Device. + * + * If the Object is a Device, and the device has a handler of + * the same type then the search is terminated in that branch. + * + * This is because the existing handler is closer in proximity + * to any more regions than the one we are trying to install. + * + ******************************************************************************/ + +static acpi_status +acpi_ev_install_handler(acpi_handle obj_handle, + u32 level, void *context, void **return_value) +{ + union acpi_operand_object *handler_obj; + union acpi_operand_object *next_handler_obj; + union acpi_operand_object *obj_desc; + struct acpi_namespace_node *node; + acpi_status status; + + ACPI_FUNCTION_NAME(ev_install_handler); + + handler_obj = (union acpi_operand_object *)context; + + /* Parameter validation */ + + if (!handler_obj) { + return (AE_OK); + } + + /* Convert and validate the device handle */ + + node = acpi_ns_validate_handle(obj_handle); + if (!node) { + return (AE_BAD_PARAMETER); + } + + /* + * We only care about regions and objects that are allowed to have + * address space handlers + */ + if ((node->type != ACPI_TYPE_DEVICE) && + (node->type != ACPI_TYPE_REGION) && (node != acpi_gbl_root_node)) { + return (AE_OK); + } + + /* Check for an existing internal object */ + + obj_desc = acpi_ns_get_attached_object(node); + if (!obj_desc) { + + /* No object, just exit */ + + return (AE_OK); + } + + /* Devices are handled different than regions */ + + if (obj_desc->common.type == ACPI_TYPE_DEVICE) { + + /* Check if this Device already has a handler for this address space */ + + next_handler_obj = obj_desc->device.handler; + while (next_handler_obj) { + + /* Found a handler, is it for the same address space? */ + + if (next_handler_obj->address_space.space_id == + handler_obj->address_space.space_id) { + ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, + "Found handler for region [%s] in device %p(%p) " + "handler %p\n", + acpi_ut_get_region_name + (handler_obj->address_space. + space_id), obj_desc, + next_handler_obj, + handler_obj)); + + /* + * Since the object we found it on was a device, then it + * means that someone has already installed a handler for + * the branch of the namespace from this device on. Just + * bail out telling the walk routine to not traverse this + * branch. This preserves the scoping rule for handlers. + */ + return (AE_CTRL_DEPTH); + } + + /* Walk the linked list of handlers attached to this device */ + + next_handler_obj = next_handler_obj->address_space.next; + } + + /* + * As long as the device didn't have a handler for this space we + * don't care about it. We just ignore it and proceed. + */ + return (AE_OK); + } + + /* Object is a Region */ + + if (obj_desc->region.space_id != handler_obj->address_space.space_id) { + + /* This region is for a different address space, just ignore it */ + + return (AE_OK); + } + + /* + * Now we have a region and it is for the handler's address space type. + * + * First disconnect region for any previous handler (if any) + */ + acpi_ev_detach_region(obj_desc, FALSE); + + /* Connect the region to the new handler */ + + status = acpi_ev_attach_region(handler_obj, obj_desc, FALSE); + return (status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_install_space_handler + * + * PARAMETERS: node - Namespace node for the device + * space_id - The address space ID + * handler - Address of the handler + * setup - Address of the setup function + * context - Value passed to the handler on each access + * + * RETURN: Status + * + * DESCRIPTION: Install a handler for all op_regions of a given space_id. + * Assumes namespace is locked + * + ******************************************************************************/ + +acpi_status +acpi_ev_install_space_handler(struct acpi_namespace_node * node, + acpi_adr_space_type space_id, + acpi_adr_space_handler handler, + acpi_adr_space_setup setup, void *context) +{ + union acpi_operand_object *obj_desc; + union acpi_operand_object *handler_obj; + acpi_status status; + acpi_object_type type; + u8 flags = 0; + + ACPI_FUNCTION_TRACE(ev_install_space_handler); + + /* + * This registration is valid for only the types below and the root. This + * is where the default handlers get placed. + */ + if ((node->type != ACPI_TYPE_DEVICE) && + (node->type != ACPI_TYPE_PROCESSOR) && + (node->type != ACPI_TYPE_THERMAL) && (node != acpi_gbl_root_node)) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + if (handler == ACPI_DEFAULT_HANDLER) { + flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED; + + switch (space_id) { + case ACPI_ADR_SPACE_SYSTEM_MEMORY: + handler = acpi_ex_system_memory_space_handler; + setup = acpi_ev_system_memory_region_setup; + break; + + case ACPI_ADR_SPACE_SYSTEM_IO: + handler = acpi_ex_system_io_space_handler; + setup = acpi_ev_io_space_region_setup; + break; + + case ACPI_ADR_SPACE_PCI_CONFIG: + handler = acpi_ex_pci_config_space_handler; + setup = acpi_ev_pci_config_region_setup; + break; + + case ACPI_ADR_SPACE_CMOS: + handler = acpi_ex_cmos_space_handler; + setup = acpi_ev_cmos_region_setup; + break; + + case ACPI_ADR_SPACE_PCI_BAR_TARGET: + handler = acpi_ex_pci_bar_space_handler; + setup = acpi_ev_pci_bar_region_setup; + break; + + case ACPI_ADR_SPACE_DATA_TABLE: + handler = acpi_ex_data_table_space_handler; + setup = NULL; + break; + + default: + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + } + + /* If the caller hasn't specified a setup routine, use the default */ + + if (!setup) { + setup = acpi_ev_default_region_setup; + } + + /* Check for an existing internal object */ + + obj_desc = acpi_ns_get_attached_object(node); + if (obj_desc) { + /* + * The attached device object already exists. Make sure the handler + * is not already installed. + */ + handler_obj = obj_desc->device.handler; + + /* Walk the handler list for this device */ + + while (handler_obj) { + + /* Same space_id indicates a handler already installed */ + + if (handler_obj->address_space.space_id == space_id) { + if (handler_obj->address_space.handler == + handler) { + /* + * It is (relatively) OK to attempt to install the SAME + * handler twice. This can easily happen with the + * PCI_Config space. + */ + status = AE_SAME_HANDLER; + goto unlock_and_exit; + } else { + /* A handler is already installed */ + + status = AE_ALREADY_EXISTS; + } + goto unlock_and_exit; + } + + /* Walk the linked list of handlers */ + + handler_obj = handler_obj->address_space.next; + } + } else { + ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, + "Creating object on Device %p while installing handler\n", + node)); + + /* obj_desc does not exist, create one */ + + if (node->type == ACPI_TYPE_ANY) { + type = ACPI_TYPE_DEVICE; + } else { + type = node->type; + } + + obj_desc = acpi_ut_create_internal_object(type); + if (!obj_desc) { + status = AE_NO_MEMORY; + goto unlock_and_exit; + } + + /* Init new descriptor */ + + obj_desc->common.type = (u8)type; + + /* Attach the new object to the Node */ + + status = acpi_ns_attach_object(node, obj_desc, type); + + /* Remove local reference to the object */ + + acpi_ut_remove_reference(obj_desc); + + if (ACPI_FAILURE(status)) { + goto unlock_and_exit; + } + } + + ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, + "Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n", + acpi_ut_get_region_name(space_id), space_id, + acpi_ut_get_node_name(node), node, obj_desc)); + + /* + * Install the handler + * + * At this point there is no existing handler. Just allocate the object + * for the handler and link it into the list. + */ + handler_obj = + acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_ADDRESS_HANDLER); + if (!handler_obj) { + status = AE_NO_MEMORY; + goto unlock_and_exit; + } + + /* Init handler obj */ + + handler_obj->address_space.space_id = (u8)space_id; + handler_obj->address_space.handler_flags = flags; + handler_obj->address_space.region_list = NULL; + handler_obj->address_space.node = node; + handler_obj->address_space.handler = handler; + handler_obj->address_space.context = context; + handler_obj->address_space.setup = setup; + + /* Install at head of Device.address_space list */ + + handler_obj->address_space.next = obj_desc->device.handler; + + /* + * The Device object is the first reference on the handler_obj. + * Each region that uses the handler adds a reference. + */ + obj_desc->device.handler = handler_obj; + + /* + * Walk the namespace finding all of the regions this + * handler will manage. + * + * Start at the device and search the branch toward + * the leaf nodes until either the leaf is encountered or + * a device is detected that has an address handler of the + * same type. + * + * In either case, back up and search down the remainder + * of the branch + */ + status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, ACPI_UINT32_MAX, + ACPI_NS_WALK_UNLOCK, + acpi_ev_install_handler, NULL, + handler_obj, NULL); + + unlock_and_exit: + return_ACPI_STATUS(status); +} diff --git a/drivers/acpi/acpica/evmisc.c b/drivers/acpi/acpica/evmisc.c index 51f537937c1f3e364ddaf9753464e8a82e1716f2..c986b2336b81d6b1b85e60ee4e2e9568e2750a33 100644 --- a/drivers/acpi/acpica/evmisc.c +++ b/drivers/acpi/acpica/evmisc.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c index 0cc6a16fedc72c9fb7767369afe9e31dddcc8699..6555e350fc1fe21087cea7e219a9c4b170d70e25 100644 --- a/drivers/acpi/acpica/evregion.c +++ b/drivers/acpi/acpica/evregion.c @@ -1,11 +1,11 @@ /****************************************************************************** * - * Module Name: evregion - ACPI address_space (op_region) handler dispatch + * Module Name: evregion - Operation Region support * *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -50,10 +50,9 @@ #define _COMPONENT ACPI_EVENTS ACPI_MODULE_NAME("evregion") +extern u8 acpi_gbl_default_address_spaces[]; + /* Local prototypes */ -static u8 -acpi_ev_has_default_handler(struct acpi_namespace_node *node, - acpi_adr_space_type space_id); static void acpi_ev_orphan_ec_reg_method(void); @@ -61,135 +60,6 @@ static acpi_status acpi_ev_reg_run(acpi_handle obj_handle, u32 level, void *context, void **return_value); -static acpi_status -acpi_ev_install_handler(acpi_handle obj_handle, - u32 level, void *context, void **return_value); - -/* These are the address spaces that will get default handlers */ - -#define ACPI_NUM_DEFAULT_SPACES 4 - -static u8 acpi_gbl_default_address_spaces[ACPI_NUM_DEFAULT_SPACES] = { - ACPI_ADR_SPACE_SYSTEM_MEMORY, - ACPI_ADR_SPACE_SYSTEM_IO, - ACPI_ADR_SPACE_PCI_CONFIG, - ACPI_ADR_SPACE_DATA_TABLE -}; - -/******************************************************************************* - * - * FUNCTION: acpi_ev_install_region_handlers - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Installs the core subsystem default address space handlers. - * - ******************************************************************************/ - -acpi_status acpi_ev_install_region_handlers(void) -{ - acpi_status status; - u32 i; - - ACPI_FUNCTION_TRACE(ev_install_region_handlers); - - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* - * All address spaces (PCI Config, EC, SMBus) are scope dependent and - * registration must occur for a specific device. - * - * In the case of the system memory and IO address spaces there is - * currently no device associated with the address space. For these we - * use the root. - * - * We install the default PCI config space handler at the root so that - * this space is immediately available even though the we have not - * enumerated all the PCI Root Buses yet. This is to conform to the ACPI - * specification which states that the PCI config space must be always - * available -- even though we are nowhere near ready to find the PCI root - * buses at this point. - * - * NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler - * has already been installed (via acpi_install_address_space_handler). - * Similar for AE_SAME_HANDLER. - */ - for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) { - status = acpi_ev_install_space_handler(acpi_gbl_root_node, - acpi_gbl_default_address_spaces - [i], - ACPI_DEFAULT_HANDLER, - NULL, NULL); - switch (status) { - case AE_OK: - case AE_SAME_HANDLER: - case AE_ALREADY_EXISTS: - - /* These exceptions are all OK */ - - status = AE_OK; - break; - - default: - - goto unlock_and_exit; - } - } - - unlock_and_exit: - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_has_default_handler - * - * PARAMETERS: node - Namespace node for the device - * space_id - The address space ID - * - * RETURN: TRUE if default handler is installed, FALSE otherwise - * - * DESCRIPTION: Check if the default handler is installed for the requested - * space ID. - * - ******************************************************************************/ - -static u8 -acpi_ev_has_default_handler(struct acpi_namespace_node *node, - acpi_adr_space_type space_id) -{ - union acpi_operand_object *obj_desc; - union acpi_operand_object *handler_obj; - - /* Must have an existing internal object */ - - obj_desc = acpi_ns_get_attached_object(node); - if (obj_desc) { - handler_obj = obj_desc->device.handler; - - /* Walk the linked list of handlers for this object */ - - while (handler_obj) { - if (handler_obj->address_space.space_id == space_id) { - if (handler_obj->address_space.handler_flags & - ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) { - return (TRUE); - } - } - - handler_obj = handler_obj->address_space.next; - } - } - - return (FALSE); -} - /******************************************************************************* * * FUNCTION: acpi_ev_initialize_op_regions @@ -239,91 +109,6 @@ acpi_status acpi_ev_initialize_op_regions(void) return_ACPI_STATUS(status); } -/******************************************************************************* - * - * FUNCTION: acpi_ev_execute_reg_method - * - * PARAMETERS: region_obj - Region object - * function - Passed to _REG: On (1) or Off (0) - * - * RETURN: Status - * - * DESCRIPTION: Execute _REG method for a region - * - ******************************************************************************/ - -acpi_status -acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function) -{ - struct acpi_evaluate_info *info; - union acpi_operand_object *args[3]; - union acpi_operand_object *region_obj2; - acpi_status status; - - ACPI_FUNCTION_TRACE(ev_execute_reg_method); - - region_obj2 = acpi_ns_get_secondary_object(region_obj); - if (!region_obj2) { - return_ACPI_STATUS(AE_NOT_EXIST); - } - - if (region_obj2->extra.method_REG == NULL) { - return_ACPI_STATUS(AE_OK); - } - - /* Allocate and initialize the evaluation information block */ - - info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); - if (!info) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - info->prefix_node = region_obj2->extra.method_REG; - info->pathname = NULL; - info->parameters = args; - info->flags = ACPI_IGNORE_RETURN_VALUE; - - /* - * The _REG method has two arguments: - * - * arg0 - Integer: - * Operation region space ID Same value as region_obj->Region.space_id - * - * arg1 - Integer: - * connection status 1 for connecting the handler, 0 for disconnecting - * the handler (Passed as a parameter) - */ - args[0] = - acpi_ut_create_integer_object((u64) region_obj->region.space_id); - if (!args[0]) { - status = AE_NO_MEMORY; - goto cleanup1; - } - - args[1] = acpi_ut_create_integer_object((u64) function); - if (!args[1]) { - status = AE_NO_MEMORY; - goto cleanup2; - } - - args[2] = NULL; /* Terminate list */ - - /* Execute the method, no return value */ - - ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname - (ACPI_TYPE_METHOD, info->prefix_node, NULL)); - - status = acpi_ns_evaluate(info); - acpi_ut_remove_reference(args[1]); - - cleanup2: - acpi_ut_remove_reference(args[0]); - - cleanup1: - ACPI_FREE(info); - return_ACPI_STATUS(status); -} - /******************************************************************************* * * FUNCTION: acpi_ev_address_space_dispatch @@ -709,351 +494,86 @@ acpi_ev_attach_region(union acpi_operand_object *handler_obj, /******************************************************************************* * - * FUNCTION: acpi_ev_install_handler - * - * PARAMETERS: walk_namespace callback - * - * DESCRIPTION: This routine installs an address handler into objects that are - * of type Region or Device. - * - * If the Object is a Device, and the device has a handler of - * the same type then the search is terminated in that branch. - * - * This is because the existing handler is closer in proximity - * to any more regions than the one we are trying to install. - * - ******************************************************************************/ - -static acpi_status -acpi_ev_install_handler(acpi_handle obj_handle, - u32 level, void *context, void **return_value) -{ - union acpi_operand_object *handler_obj; - union acpi_operand_object *next_handler_obj; - union acpi_operand_object *obj_desc; - struct acpi_namespace_node *node; - acpi_status status; - - ACPI_FUNCTION_NAME(ev_install_handler); - - handler_obj = (union acpi_operand_object *)context; - - /* Parameter validation */ - - if (!handler_obj) { - return (AE_OK); - } - - /* Convert and validate the device handle */ - - node = acpi_ns_validate_handle(obj_handle); - if (!node) { - return (AE_BAD_PARAMETER); - } - - /* - * We only care about regions and objects that are allowed to have - * address space handlers - */ - if ((node->type != ACPI_TYPE_DEVICE) && - (node->type != ACPI_TYPE_REGION) && (node != acpi_gbl_root_node)) { - return (AE_OK); - } - - /* Check for an existing internal object */ - - obj_desc = acpi_ns_get_attached_object(node); - if (!obj_desc) { - - /* No object, just exit */ - - return (AE_OK); - } - - /* Devices are handled different than regions */ - - if (obj_desc->common.type == ACPI_TYPE_DEVICE) { - - /* Check if this Device already has a handler for this address space */ - - next_handler_obj = obj_desc->device.handler; - while (next_handler_obj) { - - /* Found a handler, is it for the same address space? */ - - if (next_handler_obj->address_space.space_id == - handler_obj->address_space.space_id) { - ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, - "Found handler for region [%s] in device %p(%p) " - "handler %p\n", - acpi_ut_get_region_name - (handler_obj->address_space. - space_id), obj_desc, - next_handler_obj, - handler_obj)); - - /* - * Since the object we found it on was a device, then it - * means that someone has already installed a handler for - * the branch of the namespace from this device on. Just - * bail out telling the walk routine to not traverse this - * branch. This preserves the scoping rule for handlers. - */ - return (AE_CTRL_DEPTH); - } - - /* Walk the linked list of handlers attached to this device */ - - next_handler_obj = next_handler_obj->address_space.next; - } - - /* - * As long as the device didn't have a handler for this space we - * don't care about it. We just ignore it and proceed. - */ - return (AE_OK); - } - - /* Object is a Region */ - - if (obj_desc->region.space_id != handler_obj->address_space.space_id) { - - /* This region is for a different address space, just ignore it */ - - return (AE_OK); - } - - /* - * Now we have a region and it is for the handler's address space type. - * - * First disconnect region for any previous handler (if any) - */ - acpi_ev_detach_region(obj_desc, FALSE); - - /* Connect the region to the new handler */ - - status = acpi_ev_attach_region(handler_obj, obj_desc, FALSE); - return (status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_install_space_handler + * FUNCTION: acpi_ev_execute_reg_method * - * PARAMETERS: node - Namespace node for the device - * space_id - The address space ID - * handler - Address of the handler - * setup - Address of the setup function - * context - Value passed to the handler on each access + * PARAMETERS: region_obj - Region object + * function - Passed to _REG: On (1) or Off (0) * * RETURN: Status * - * DESCRIPTION: Install a handler for all op_regions of a given space_id. - * Assumes namespace is locked + * DESCRIPTION: Execute _REG method for a region * ******************************************************************************/ acpi_status -acpi_ev_install_space_handler(struct acpi_namespace_node * node, - acpi_adr_space_type space_id, - acpi_adr_space_handler handler, - acpi_adr_space_setup setup, void *context) +acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function) { - union acpi_operand_object *obj_desc; - union acpi_operand_object *handler_obj; + struct acpi_evaluate_info *info; + union acpi_operand_object *args[3]; + union acpi_operand_object *region_obj2; acpi_status status; - acpi_object_type type; - u8 flags = 0; - ACPI_FUNCTION_TRACE(ev_install_space_handler); - - /* - * This registration is valid for only the types below and the root. This - * is where the default handlers get placed. - */ - if ((node->type != ACPI_TYPE_DEVICE) && - (node->type != ACPI_TYPE_PROCESSOR) && - (node->type != ACPI_TYPE_THERMAL) && (node != acpi_gbl_root_node)) { - status = AE_BAD_PARAMETER; - goto unlock_and_exit; - } + ACPI_FUNCTION_TRACE(ev_execute_reg_method); - if (handler == ACPI_DEFAULT_HANDLER) { - flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED; - - switch (space_id) { - case ACPI_ADR_SPACE_SYSTEM_MEMORY: - handler = acpi_ex_system_memory_space_handler; - setup = acpi_ev_system_memory_region_setup; - break; - - case ACPI_ADR_SPACE_SYSTEM_IO: - handler = acpi_ex_system_io_space_handler; - setup = acpi_ev_io_space_region_setup; - break; - - case ACPI_ADR_SPACE_PCI_CONFIG: - handler = acpi_ex_pci_config_space_handler; - setup = acpi_ev_pci_config_region_setup; - break; - - case ACPI_ADR_SPACE_CMOS: - handler = acpi_ex_cmos_space_handler; - setup = acpi_ev_cmos_region_setup; - break; - - case ACPI_ADR_SPACE_PCI_BAR_TARGET: - handler = acpi_ex_pci_bar_space_handler; - setup = acpi_ev_pci_bar_region_setup; - break; - - case ACPI_ADR_SPACE_DATA_TABLE: - handler = acpi_ex_data_table_space_handler; - setup = NULL; - break; - - default: - status = AE_BAD_PARAMETER; - goto unlock_and_exit; - } + region_obj2 = acpi_ns_get_secondary_object(region_obj); + if (!region_obj2) { + return_ACPI_STATUS(AE_NOT_EXIST); } - /* If the caller hasn't specified a setup routine, use the default */ - - if (!setup) { - setup = acpi_ev_default_region_setup; + if (region_obj2->extra.method_REG == NULL) { + return_ACPI_STATUS(AE_OK); } - /* Check for an existing internal object */ - - obj_desc = acpi_ns_get_attached_object(node); - if (obj_desc) { - /* - * The attached device object already exists. Make sure the handler - * is not already installed. - */ - handler_obj = obj_desc->device.handler; - - /* Walk the handler list for this device */ - - while (handler_obj) { - - /* Same space_id indicates a handler already installed */ - - if (handler_obj->address_space.space_id == space_id) { - if (handler_obj->address_space.handler == - handler) { - /* - * It is (relatively) OK to attempt to install the SAME - * handler twice. This can easily happen with the - * PCI_Config space. - */ - status = AE_SAME_HANDLER; - goto unlock_and_exit; - } else { - /* A handler is already installed */ - - status = AE_ALREADY_EXISTS; - } - goto unlock_and_exit; - } - - /* Walk the linked list of handlers */ - - handler_obj = handler_obj->address_space.next; - } - } else { - ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, - "Creating object on Device %p while installing handler\n", - node)); - - /* obj_desc does not exist, create one */ - - if (node->type == ACPI_TYPE_ANY) { - type = ACPI_TYPE_DEVICE; - } else { - type = node->type; - } - - obj_desc = acpi_ut_create_internal_object(type); - if (!obj_desc) { - status = AE_NO_MEMORY; - goto unlock_and_exit; - } - - /* Init new descriptor */ - - obj_desc->common.type = (u8) type; - - /* Attach the new object to the Node */ - - status = acpi_ns_attach_object(node, obj_desc, type); - - /* Remove local reference to the object */ - - acpi_ut_remove_reference(obj_desc); + /* Allocate and initialize the evaluation information block */ - if (ACPI_FAILURE(status)) { - goto unlock_and_exit; - } + info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); + if (!info) { + return_ACPI_STATUS(AE_NO_MEMORY); } - ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, - "Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n", - acpi_ut_get_region_name(space_id), space_id, - acpi_ut_get_node_name(node), node, obj_desc)); + info->prefix_node = region_obj2->extra.method_REG; + info->pathname = NULL; + info->parameters = args; + info->flags = ACPI_IGNORE_RETURN_VALUE; /* - * Install the handler + * The _REG method has two arguments: + * + * arg0 - Integer: + * Operation region space ID Same value as region_obj->Region.space_id * - * At this point there is no existing handler. Just allocate the object - * for the handler and link it into the list. + * arg1 - Integer: + * connection status 1 for connecting the handler, 0 for disconnecting + * the handler (Passed as a parameter) */ - handler_obj = - acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_ADDRESS_HANDLER); - if (!handler_obj) { + args[0] = + acpi_ut_create_integer_object((u64)region_obj->region.space_id); + if (!args[0]) { status = AE_NO_MEMORY; - goto unlock_and_exit; + goto cleanup1; } - /* Init handler obj */ + args[1] = acpi_ut_create_integer_object((u64)function); + if (!args[1]) { + status = AE_NO_MEMORY; + goto cleanup2; + } - handler_obj->address_space.space_id = (u8) space_id; - handler_obj->address_space.handler_flags = flags; - handler_obj->address_space.region_list = NULL; - handler_obj->address_space.node = node; - handler_obj->address_space.handler = handler; - handler_obj->address_space.context = context; - handler_obj->address_space.setup = setup; + args[2] = NULL; /* Terminate list */ - /* Install at head of Device.address_space list */ + /* Execute the method, no return value */ - handler_obj->address_space.next = obj_desc->device.handler; + ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname + (ACPI_TYPE_METHOD, info->prefix_node, NULL)); - /* - * The Device object is the first reference on the handler_obj. - * Each region that uses the handler adds a reference. - */ - obj_desc->device.handler = handler_obj; + status = acpi_ns_evaluate(info); + acpi_ut_remove_reference(args[1]); - /* - * Walk the namespace finding all of the regions this - * handler will manage. - * - * Start at the device and search the branch toward - * the leaf nodes until either the leaf is encountered or - * a device is detected that has an address handler of the - * same type. - * - * In either case, back up and search down the remainder - * of the branch - */ - status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, ACPI_UINT32_MAX, - ACPI_NS_WALK_UNLOCK, - acpi_ev_install_handler, NULL, - handler_obj, NULL); + cleanup2: + acpi_ut_remove_reference(args[0]); - unlock_and_exit: + cleanup1: + ACPI_FREE(info); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/evrgnini.c b/drivers/acpi/acpica/evrgnini.c index 1474241bfc7e33a45b295ffd81e06737b62d1af7..3bb616794b3b46fe5aaaaa7b77335523b351b159 100644 --- a/drivers/acpi/acpica/evrgnini.c +++ b/drivers/acpi/acpica/evrgnini.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/evsci.c b/drivers/acpi/acpica/evsci.c index f9661e2b46a981d8a53dca19425cfbd2b046ffbb..f4b43bede01567c769344caf0fd0472c40132244 100644 --- a/drivers/acpi/acpica/evsci.c +++ b/drivers/acpi/acpica/evsci.c @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -89,7 +89,7 @@ static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context) */ interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list); - return_UINT32(interrupt_handled); + return_VALUE(interrupt_handled); } /******************************************************************************* @@ -120,7 +120,7 @@ u32 ACPI_SYSTEM_XFACE acpi_ev_gpe_xrupt_handler(void *context) interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list); - return_UINT32(interrupt_handled); + return_VALUE(interrupt_handled); } /****************************************************************************** diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c index ae668f32cf16f8c0dbf8b22d4629a99a8ded54a8..ddffd6847914d5544688a6e35b471e2826b8c20b 100644 --- a/drivers/acpi/acpica/evxface.c +++ b/drivers/acpi/acpica/evxface.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -56,13 +56,13 @@ ACPI_MODULE_NAME("evxface") * * FUNCTION: acpi_install_notify_handler * - * PARAMETERS: Device - The device for which notifies will be handled + * PARAMETERS: device - The device for which notifies will be handled * handler_type - The type of handler: * ACPI_SYSTEM_NOTIFY: System Handler (00-7F) * ACPI_DEVICE_NOTIFY: Device Handler (80-FF) * ACPI_ALL_NOTIFY: Both System and Device - * Handler - Address of the handler - * Context - Value passed to the handler on each GPE + * handler - Address of the handler + * context - Value passed to the handler on each GPE * * RETURN: Status * @@ -217,12 +217,12 @@ ACPI_EXPORT_SYMBOL(acpi_install_notify_handler) * * FUNCTION: acpi_remove_notify_handler * - * PARAMETERS: Device - The device for which the handler is installed + * PARAMETERS: device - The device for which the handler is installed * handler_type - The type of handler: * ACPI_SYSTEM_NOTIFY: System Handler (00-7F) * ACPI_DEVICE_NOTIFY: Device Handler (80-FF) * ACPI_ALL_NOTIFY: Both System and Device - * Handler - Address of the handler + * handler - Address of the handler * * RETURN: Status * @@ -249,7 +249,8 @@ acpi_remove_notify_handler(acpi_handle device, (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { return_ACPI_STATUS(AE_BAD_PARAMETER); } - /* Make sure all deferred tasks are completed */ + + /* Make sure all deferred notify tasks are completed */ acpi_os_wait_events_complete(); @@ -596,7 +597,7 @@ acpi_install_gpe_handler(acpi_handle gpe_device, return_ACPI_STATUS(status); } - /* Allocate memory for the handler object */ + /* Allocate and init handler object (before lock) */ handler = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_handler_info)); if (!handler) { @@ -622,16 +623,15 @@ acpi_install_gpe_handler(acpi_handle gpe_device, goto free_and_exit; } - /* Allocate and init handler object */ - handler->address = address; handler->context = context; handler->method_node = gpe_event_info->dispatch.method_node; - handler->original_flags = gpe_event_info->flags & - (ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); + handler->original_flags = (u8)(gpe_event_info->flags & + (ACPI_GPE_XRUPT_TYPE_MASK | + ACPI_GPE_DISPATCH_MASK)); /* - * If the GPE is associated with a method, it might have been enabled + * If the GPE is associated with a method, it may have been enabled * automatically during initialization, in which case it has to be * disabled now to avoid spurious execution of the handler. */ @@ -646,7 +646,7 @@ acpi_install_gpe_handler(acpi_handle gpe_device, gpe_event_info->dispatch.handler = handler; - /* Setup up dispatch flags to indicate handler (vs. method) */ + /* Setup up dispatch flags to indicate handler (vs. method/notify) */ gpe_event_info->flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); @@ -697,7 +697,7 @@ acpi_remove_gpe_handler(acpi_handle gpe_device, return_ACPI_STATUS(AE_BAD_PARAMETER); } - /* Make sure all deferred tasks are completed */ + /* Make sure all deferred GPE tasks are completed */ acpi_os_wait_events_complete(); @@ -747,10 +747,10 @@ acpi_remove_gpe_handler(acpi_handle gpe_device, * enabled, it should be enabled at this point to restore the * post-initialization configuration. */ - - if ((handler->original_flags & ACPI_GPE_DISPATCH_METHOD) - && handler->originally_enabled) + if ((handler->original_flags & ACPI_GPE_DISPATCH_METHOD) && + handler->originally_enabled) { (void)acpi_ev_add_gpe_reference(gpe_event_info); + } /* Now we can free the handler object */ diff --git a/drivers/acpi/acpica/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c index 35520c6eeefb4b52fbab8971fd0c36a8ae115a46..d6e4e42316db51267a901d0d45487f0e2df4363a 100644 --- a/drivers/acpi/acpica/evxfevnt.c +++ b/drivers/acpi/acpica/evxfevnt.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -61,7 +61,6 @@ ACPI_MODULE_NAME("evxfevnt") * DESCRIPTION: Transfers the system into ACPI mode. * ******************************************************************************/ - acpi_status acpi_enable(void) { acpi_status status; @@ -210,8 +209,8 @@ ACPI_EXPORT_SYMBOL(acpi_enable_event) * * FUNCTION: acpi_disable_event * - * PARAMETERS: Event - The fixed eventto be enabled - * Flags - Reserved + * PARAMETERS: event - The fixed event to be disabled + * flags - Reserved * * RETURN: Status * diff --git a/drivers/acpi/acpica/evxfgpe.c b/drivers/acpi/acpica/evxfgpe.c index 3f30e753b652ebe4db8e40588479a1aa13b5b76a..aff4cc2612115304f41ea11a6aa57a5038a6f101 100644 --- a/drivers/acpi/acpica/evxfgpe.c +++ b/drivers/acpi/acpica/evxfgpe.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -51,7 +51,7 @@ ACPI_MODULE_NAME("evxfgpe") #if (!ACPI_REDUCED_HARDWARE) /* Entire module */ -/****************************************************************************** +/******************************************************************************* * * FUNCTION: acpi_update_all_gpes * @@ -172,6 +172,7 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number) acpi_os_release_lock(acpi_gbl_gpe_lock, flags); return_ACPI_STATUS(status); } + ACPI_EXPORT_SYMBOL(acpi_disable_gpe) @@ -225,7 +226,7 @@ acpi_setup_gpe_for_wake(acpi_handle wake_device, ACPI_CAST_PTR(struct acpi_namespace_node, wake_device); } - /* Validate WakeDevice is of type Device */ + /* Validate wake_device is of type Device */ if (device_node->type != ACPI_TYPE_DEVICE) { return_ACPI_STATUS (AE_BAD_PARAMETER); @@ -432,8 +433,8 @@ ACPI_EXPORT_SYMBOL(acpi_clear_gpe) * * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 * gpe_number - GPE level within the GPE block - * event_status - Where the current status of the event will - * be returned + * event_status - Where the current status of the event + * will be returned * * RETURN: Status * diff --git a/drivers/acpi/acpica/evxfregn.c b/drivers/acpi/acpica/evxfregn.c index 96b412d0395017fd41e12594d864ade0c949ae73..96c9e5f355aed40f7e07fc598d60b61907c501a6 100644 --- a/drivers/acpi/acpica/evxfregn.c +++ b/drivers/acpi/acpica/evxfregn.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exconfig.c b/drivers/acpi/acpica/exconfig.c index 16219bde48da2ca4a7b2a7c60e427530da395a10..d93b70be60adf071c132687b208241d233bb4f3a 100644 --- a/drivers/acpi/acpica/exconfig.c +++ b/drivers/acpi/acpica/exconfig.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -48,6 +48,7 @@ #include "actables.h" #include "acdispat.h" #include "acevents.h" +#include "amlcode.h" #define _COMPONENT ACPI_EXECUTER ACPI_MODULE_NAME("exconfig") @@ -120,8 +121,11 @@ acpi_ex_add_table(u32 table_index, acpi_ns_exec_module_code_list(); acpi_ex_enter_interpreter(); - /* Update GPEs for any new _Lxx/_Exx methods. Ignore errors */ - + /* + * Update GPEs for any new _Lxx/_Exx methods. Ignore errors. The host is + * responsible for discovering any new wake GPEs by running _PRW methods + * that may have been loaded by this table. + */ status = acpi_tb_get_owner_id(table_index, &owner_id); if (ACPI_SUCCESS(status)) { acpi_ev_update_gpes(owner_id); @@ -158,12 +162,12 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, ACPI_FUNCTION_TRACE(ex_load_table_op); - /* Validate lengths for the signature_string, OEMIDString, OEMtable_iD */ + /* Validate lengths for the Signature, oem_id, and oem_table_id strings */ if ((operand[0]->string.length > ACPI_NAME_SIZE) || (operand[1]->string.length > ACPI_OEM_ID_SIZE) || (operand[2]->string.length > ACPI_OEM_TABLE_ID_SIZE)) { - return_ACPI_STATUS(AE_BAD_PARAMETER); + return_ACPI_STATUS(AE_AML_STRING_LIMIT); } /* Find the ACPI table in the RSDT/XSDT */ @@ -210,8 +214,8 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, /* parameter_path (optional parameter) */ if (operand[4]->string.length > 0) { - if ((operand[4]->string.pointer[0] != '\\') && - (operand[4]->string.pointer[0] != '^')) { + if ((operand[4]->string.pointer[0] != AML_ROOT_PREFIX) && + (operand[4]->string.pointer[0] != AML_PARENT_PREFIX)) { /* * Path is not absolute, so it will be relative to the node * referenced by the root_path_string (or the NS root if omitted) @@ -301,7 +305,7 @@ acpi_ex_region_read(union acpi_operand_object *obj_desc, u32 length, u8 *buffer) acpi_ev_address_space_dispatch(obj_desc, NULL, ACPI_READ, region_offset, 8, &value); if (ACPI_FAILURE(status)) { - return status; + return (status); } *buffer = (u8)value; @@ -309,7 +313,7 @@ acpi_ex_region_read(union acpi_operand_object *obj_desc, u32 length, u8 *buffer) region_offset++; } - return AE_OK; + return (AE_OK); } /******************************************************************************* diff --git a/drivers/acpi/acpica/exconvrt.c b/drivers/acpi/acpica/exconvrt.c index 4492a4e030223ba6604842e5415fe2001a1d3e18..d2b9613bbf01d231e72f44d87381e83ab87f11e4 100644 --- a/drivers/acpi/acpica/exconvrt.c +++ b/drivers/acpi/acpica/exconvrt.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -176,7 +176,7 @@ acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc, /* Save the Result */ - acpi_ex_truncate_for32bit_table(return_desc); + (void)acpi_ex_truncate_for32bit_table(return_desc); *result_desc = return_desc; return_ACPI_STATUS(AE_OK); } diff --git a/drivers/acpi/acpica/excreate.c b/drivers/acpi/acpica/excreate.c index 66554bc6f9a83e15f97199ebd7bfb58fe24b3694..26a13f67977ea11248cc54ec9f034ecf1a584e45 100644 --- a/drivers/acpi/acpica/excreate.c +++ b/drivers/acpi/acpica/excreate.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exdebug.c b/drivers/acpi/acpica/exdebug.c index d7c9f51608a715cf9d2196ef165e1f717af91166..7eb853cd279f776f5b384543dba38fdedfafff38 100644 --- a/drivers/acpi/acpica/exdebug.c +++ b/drivers/acpi/acpica/exdebug.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exdump.c b/drivers/acpi/acpica/exdump.c index 858b43a7dcf6a0447eabf03408c28bb88a12417f..e5a3c249f7fad23c544a856504d13d33134c104e 100644 --- a/drivers/acpi/acpica/exdump.c +++ b/drivers/acpi/acpica/exdump.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -464,9 +464,8 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) ACPI_FUNCTION_NAME(ex_dump_operand) - if (! - ((ACPI_LV_EXEC & acpi_dbg_level) - && (_COMPONENT & acpi_dbg_layer))) { + /* Check if debug output enabled */ + if (!ACPI_IS_DEBUG_ENABLED(ACPI_LV_EXEC, _COMPONENT)) { return; } @@ -811,9 +810,10 @@ void acpi_ex_dump_namespace_node(struct acpi_namespace_node *node, u32 flags) ACPI_FUNCTION_ENTRY(); if (!flags) { - if (! - ((ACPI_LV_OBJECTS & acpi_dbg_level) - && (_COMPONENT & acpi_dbg_layer))) { + + /* Check if debug output enabled */ + + if (!ACPI_IS_DEBUG_ENABLED(ACPI_LV_OBJECTS, _COMPONENT)) { return; } } @@ -999,9 +999,10 @@ acpi_ex_dump_object_descriptor(union acpi_operand_object *obj_desc, u32 flags) } if (!flags) { - if (! - ((ACPI_LV_OBJECTS & acpi_dbg_level) - && (_COMPONENT & acpi_dbg_layer))) { + + /* Check if debug output enabled */ + + if (!ACPI_IS_DEBUG_ENABLED(ACPI_LV_OBJECTS, _COMPONENT)) { return_VOID; } } diff --git a/drivers/acpi/acpica/exfield.c b/drivers/acpi/acpica/exfield.c index ebc55fbf3ff7cb5e76d7e7a47d0d2e3477fd237e..7d4bae71e8c62da6399bc6af7e0f3fd132efa574 100644 --- a/drivers/acpi/acpica/exfield.c +++ b/drivers/acpi/acpica/exfield.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exfldio.c b/drivers/acpi/acpica/exfldio.c index aa2ccfb7cb61218f7d8a4b7da30c36941d7ccca9..ec7f5690031b0c5c3c0e1b097f03943b3e07f510 100644 --- a/drivers/acpi/acpica/exfldio.c +++ b/drivers/acpi/acpica/exfldio.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -329,7 +329,6 @@ acpi_ex_access_region(union acpi_operand_object *obj_desc, static u8 acpi_ex_register_overflow(union acpi_operand_object *obj_desc, u64 value) { - ACPI_FUNCTION_NAME(ex_register_overflow); if (obj_desc->common_field.bit_length >= ACPI_INTEGER_BIT_SIZE) { /* diff --git a/drivers/acpi/acpica/exmisc.c b/drivers/acpi/acpica/exmisc.c index 84058705ed129881fdf92a169399be49b2d57013..72a2a13b6d36de72eb97cf7d38aacb0cada1587b 100644 --- a/drivers/acpi/acpica/exmisc.c +++ b/drivers/acpi/acpica/exmisc.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exmutex.c b/drivers/acpi/acpica/exmutex.c index d1f449d93dcf2de4a51755bc08ad3407a218f54c..7be0205ad06797a1037977c6757a879f28bb1810 100644 --- a/drivers/acpi/acpica/exmutex.c +++ b/drivers/acpi/acpica/exmutex.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -377,7 +377,8 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, return_ACPI_STATUS(AE_AML_MUTEX_NOT_ACQUIRED); } - /* Must have a valid thread. */ + /* Must have a valid thread ID */ + if (!walk_state->thread) { ACPI_ERROR((AE_INFO, "Cannot release Mutex [%4.4s], null thread info", diff --git a/drivers/acpi/acpica/exnames.c b/drivers/acpi/acpica/exnames.c index 2ff578a16adc4c13f0a6fac1cf358e4ae9c4c422..14689dec496095ae2735c197a5ff749aa823f212 100644 --- a/drivers/acpi/acpica/exnames.c +++ b/drivers/acpi/acpica/exnames.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exoparg1.c b/drivers/acpi/acpica/exoparg1.c index bbf01e9bf057a724c0ddba929bba613dfeaa7f32..b60c877f5906d9d8b7d00d9a022d3105f4aa2c2a 100644 --- a/drivers/acpi/acpica/exoparg1.c +++ b/drivers/acpi/acpica/exoparg1.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -948,13 +948,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) */ return_desc = acpi_ut_create_integer_object((u64) - temp_desc-> - buffer. - pointer - [operand - [0]-> - reference. - value]); + temp_desc->buffer.pointer[operand[0]->reference.value]); if (!return_desc) { status = AE_NO_MEMORY; goto cleanup; diff --git a/drivers/acpi/acpica/exoparg2.c b/drivers/acpi/acpica/exoparg2.c index ee5634a074c4726c177f90791bd6430224cfe21e..e491e46f17df6d14abd26ff45f9c383cd5a0cfee 100644 --- a/drivers/acpi/acpica/exoparg2.c +++ b/drivers/acpi/acpica/exoparg2.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exoparg3.c b/drivers/acpi/acpica/exoparg3.c index 2c89b4651f08e7c2a4cff33d6146c006c80b4a95..2d7491f3126ef906ee6e589494f7936f20885166 100644 --- a/drivers/acpi/acpica/exoparg3.c +++ b/drivers/acpi/acpica/exoparg3.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exoparg6.c b/drivers/acpi/acpica/exoparg6.c index 3e08695c3b3008d280c914741986ba4e011277fa..b76b97002dffd1701741b5fe18031f3104580dfb 100644 --- a/drivers/acpi/acpica/exoparg6.c +++ b/drivers/acpi/acpica/exoparg6.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exprep.c b/drivers/acpi/acpica/exprep.c index ba9db4de7c892509d0eda4862e2ca03e3ba1c395..d6eab81f54fb1ceab1146d69d4d343e9e01ca80b 100644 --- a/drivers/acpi/acpica/exprep.c +++ b/drivers/acpi/acpica/exprep.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -276,7 +276,7 @@ acpi_ex_decode_field_access(union acpi_operand_object *obj_desc, /* Invalid field access type */ ACPI_ERROR((AE_INFO, "Unknown field access type 0x%X", access)); - return_UINT32(0); + return_VALUE(0); } if (obj_desc->common.type == ACPI_TYPE_BUFFER_FIELD) { @@ -289,7 +289,7 @@ acpi_ex_decode_field_access(union acpi_operand_object *obj_desc, } *return_byte_alignment = byte_alignment; - return_UINT32(bit_length); + return_VALUE(bit_length); } /******************************************************************************* diff --git a/drivers/acpi/acpica/exregion.c b/drivers/acpi/acpica/exregion.c index 1db2c0bfde0b22f31aa7c88dc190bd48455faaf2..182abaf045e165588606bd4a52de7c98413717c1 100644 --- a/drivers/acpi/acpica/exregion.c +++ b/drivers/acpi/acpica/exregion.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -142,9 +142,9 @@ acpi_ex_system_memory_space_handler(u32 function, } /* - * Attempt to map from the requested address to the end of the region. - * However, we will never map more than one page, nor will we cross - * a page boundary. + * October 2009: Attempt to map from the requested address to the + * end of the region. However, we will never map more than one + * page, nor will we cross a page boundary. */ map_length = (acpi_size) ((mem_info->address + mem_info->length) - address); @@ -154,12 +154,15 @@ acpi_ex_system_memory_space_handler(u32 function, * a page boundary, just map up to the page boundary, do not cross. * On some systems, crossing a page boundary while mapping regions * can cause warnings if the pages have different attributes - * due to resource management + * due to resource management. + * + * This has the added benefit of constraining a single mapping to + * one page, which is similar to the original code that used a 4k + * maximum window. */ page_boundary_map_length = ACPI_ROUND_UP(address, ACPI_DEFAULT_PAGE_SIZE) - address; - - if (!page_boundary_map_length) { + if (page_boundary_map_length == 0) { page_boundary_map_length = ACPI_DEFAULT_PAGE_SIZE; } @@ -236,19 +239,19 @@ acpi_ex_system_memory_space_handler(u32 function, switch (bit_width) { case 8: - ACPI_SET8(logical_addr_ptr) = (u8) * value; + ACPI_SET8(logical_addr_ptr, *value); break; case 16: - ACPI_SET16(logical_addr_ptr) = (u16) * value; + ACPI_SET16(logical_addr_ptr, *value); break; case 32: - ACPI_SET32(logical_addr_ptr) = (u32) * value; + ACPI_SET32(logical_addr_ptr, *value); break; case 64: - ACPI_SET64(logical_addr_ptr) = (u64) * value; + ACPI_SET64(logical_addr_ptr, *value); break; default: diff --git a/drivers/acpi/acpica/exresnte.c b/drivers/acpi/acpica/exresnte.c index 6239956786ebad63828e95f7a4e7a2445bc2e0d6..8565b6bd12bb41a886aa8ad94d9355dd74d3a942 100644 --- a/drivers/acpi/acpica/exresnte.c +++ b/drivers/acpi/acpica/exresnte.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exresolv.c b/drivers/acpi/acpica/exresolv.c index cc176b245e22063bccb92bfa48ed0b8fb7a6df8d..e4f9dfbb2a13f737e37e65bba8d374a7e673a987 100644 --- a/drivers/acpi/acpica/exresolv.c +++ b/drivers/acpi/acpica/exresolv.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exresop.c b/drivers/acpi/acpica/exresop.c index b9ebff2f6a094ff7401c39142383654891b945c0..9fb9f5e9a4daefe2f3a477eeb222d6ba1e560719 100644 --- a/drivers/acpi/acpica/exresop.c +++ b/drivers/acpi/acpica/exresop.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exstore.c b/drivers/acpi/acpica/exstore.c index 90431f12f8318e6fdb99d9dc06a6c338c8aa5850..93c6049c2d754d3e621729599510344e2d06d7dc 100644 --- a/drivers/acpi/acpica/exstore.c +++ b/drivers/acpi/acpica/exstore.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -487,14 +487,33 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc, default: ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Storing %s (%p) directly into node (%p) with no implicit conversion\n", + "Storing [%s] (%p) directly into node [%s] (%p)" + " with no implicit conversion\n", acpi_ut_get_object_type_name(source_desc), - source_desc, node)); + source_desc, + acpi_ut_get_object_type_name(target_desc), + node)); - /* No conversions for all other types. Just attach the source object */ + /* + * No conversions for all other types. Directly store a copy of + * the source object. NOTE: This is a departure from the ACPI + * spec, which states "If conversion is impossible, abort the + * running control method". + * + * This code implements "If conversion is impossible, treat the + * Store operation as a CopyObject". + */ + status = + acpi_ut_copy_iobject_to_iobject(source_desc, &new_desc, + walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } - status = acpi_ns_attach_object(node, source_desc, - source_desc->common.type); + status = + acpi_ns_attach_object(node, new_desc, + new_desc->common.type); + acpi_ut_remove_reference(new_desc); break; } diff --git a/drivers/acpi/acpica/exstoren.c b/drivers/acpi/acpica/exstoren.c index 87153bbc4b438c0236bd3f47936184874798b304..1cefe777068eef26b2d66851418c7992ede3244a 100644 --- a/drivers/acpi/acpica/exstoren.c +++ b/drivers/acpi/acpica/exstoren.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -253,7 +253,7 @@ acpi_ex_store_object_to_object(union acpi_operand_object *source_desc, /* Truncate value if we are executing from a 32-bit ACPI table */ - acpi_ex_truncate_for32bit_table(dest_desc); + (void)acpi_ex_truncate_for32bit_table(dest_desc); break; case ACPI_TYPE_STRING: diff --git a/drivers/acpi/acpica/exstorob.c b/drivers/acpi/acpica/exstorob.c index b5f339cb13051cb244926c0856cc50af2b1d1c7a..26e371073b1aa881b1bac40a0b6579da0f5a2c12 100644 --- a/drivers/acpi/acpica/exstorob.c +++ b/drivers/acpi/acpica/exstorob.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exsystem.c b/drivers/acpi/acpica/exsystem.c index c8a0ad5c1f55894c9bfe24fa2e4b4a2c94a481a9..6578dee2e51b276f33154cdc4b2fa868f94245d5 100644 --- a/drivers/acpi/acpica/exsystem.c +++ b/drivers/acpi/acpica/exsystem.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exutils.c b/drivers/acpi/acpica/exutils.c index 264d22d8018c14f50fd7cf338339247692be136d..b205cbb4b50c3494c89f025f4c847134175898b9 100644 --- a/drivers/acpi/acpica/exutils.c +++ b/drivers/acpi/acpica/exutils.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -202,35 +202,39 @@ void acpi_ex_relinquish_interpreter(void) * * PARAMETERS: obj_desc - Object to be truncated * - * RETURN: none + * RETURN: TRUE if a truncation was performed, FALSE otherwise. * * DESCRIPTION: Truncate an ACPI Integer to 32 bits if the execution mode is * 32-bit, as determined by the revision of the DSDT. * ******************************************************************************/ -void acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc) +u8 acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc) { ACPI_FUNCTION_ENTRY(); /* * Object must be a valid number and we must be executing - * a control method. NS node could be there for AML_INT_NAMEPATH_OP. + * a control method. Object could be NS node for AML_INT_NAMEPATH_OP. */ if ((!obj_desc) || (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != ACPI_DESC_TYPE_OPERAND) || (obj_desc->common.type != ACPI_TYPE_INTEGER)) { - return; + return (FALSE); } - if (acpi_gbl_integer_byte_width == 4) { + if ((acpi_gbl_integer_byte_width == 4) && + (obj_desc->integer.value > (u64)ACPI_UINT32_MAX)) { /* - * We are running a method that exists in a 32-bit ACPI table. + * We are executing in a 32-bit ACPI table. * Truncate the value to 32 bits by zeroing out the upper 32-bit field */ - obj_desc->integer.value &= (u64) ACPI_UINT32_MAX; + obj_desc->integer.value &= (u64)ACPI_UINT32_MAX; + return (TRUE); } + + return (FALSE); } /******************************************************************************* @@ -336,7 +340,7 @@ static u32 acpi_ex_digits_needed(u64 value, u32 base) /* u64 is unsigned, so we don't worry about a '-' prefix */ if (value == 0) { - return_UINT32(1); + return_VALUE(1); } current_value = value; @@ -350,7 +354,7 @@ static u32 acpi_ex_digits_needed(u64 value, u32 base) num_digits++; } - return_UINT32(num_digits); + return_VALUE(num_digits); } /******************************************************************************* diff --git a/drivers/acpi/acpica/hwacpi.c b/drivers/acpi/acpica/hwacpi.c index 90a9aea1cee96779dccd7950acc624dd75b9a6de..deb3f61e2bd1816a26cb75cf62567240e6c030a5 100644 --- a/drivers/acpi/acpica/hwacpi.c +++ b/drivers/acpi/acpica/hwacpi.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -108,8 +108,7 @@ acpi_status acpi_hw_set_mode(u32 mode) * enable bits to default */ status = acpi_hw_write_port(acpi_gbl_FADT.smi_command, - (u32) acpi_gbl_FADT.acpi_disable, - 8); + (u32)acpi_gbl_FADT.acpi_disable, 8); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Attempting to enable Legacy (non-ACPI) mode\n")); break; @@ -152,18 +151,18 @@ u32 acpi_hw_get_mode(void) * system does not support mode transition. */ if (!acpi_gbl_FADT.smi_command) { - return_UINT32(ACPI_SYS_MODE_ACPI); + return_VALUE(ACPI_SYS_MODE_ACPI); } status = acpi_read_bit_register(ACPI_BITREG_SCI_ENABLE, &value); if (ACPI_FAILURE(status)) { - return_UINT32(ACPI_SYS_MODE_LEGACY); + return_VALUE(ACPI_SYS_MODE_LEGACY); } if (value) { - return_UINT32(ACPI_SYS_MODE_ACPI); + return_VALUE(ACPI_SYS_MODE_ACPI); } else { - return_UINT32(ACPI_SYS_MODE_LEGACY); + return_VALUE(ACPI_SYS_MODE_LEGACY); } } diff --git a/drivers/acpi/acpica/hwesleep.c b/drivers/acpi/acpica/hwesleep.c index 94996f9ae3ad164636364af38d6ce0b2524cdd72..5e5f76230f5eb673057f86c7d61c24539471a1eb 100644 --- a/drivers/acpi/acpica/hwesleep.c +++ b/drivers/acpi/acpica/hwesleep.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -200,7 +200,6 @@ acpi_status acpi_hw_extended_wake_prep(u8 sleep_state) * FUNCTION: acpi_hw_extended_wake * * PARAMETERS: sleep_state - Which sleep state we just exited - * flags - Reserved, set to zero * * RETURN: Status * diff --git a/drivers/acpi/acpica/hwgpe.c b/drivers/acpi/acpica/hwgpe.c index 64560045052dd152d70e4b404af9a11d1b43b57e..20d02e93c99021e10038849b5290d77e360b55fc 100644 --- a/drivers/acpi/acpica/hwgpe.c +++ b/drivers/acpi/acpica/hwgpe.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -69,8 +69,10 @@ acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, u32 acpi_hw_get_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info) { - return (u32)1 << (gpe_event_info->gpe_number - - gpe_event_info->register_info->base_gpe_number); + + return ((u32)1 << + (gpe_event_info->gpe_number - + gpe_event_info->register_info->base_gpe_number)); } /****************************************************************************** @@ -133,7 +135,7 @@ acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u32 action) break; default: - ACPI_ERROR((AE_INFO, "Invalid GPE Action, %u\n", action)); + ACPI_ERROR((AE_INFO, "Invalid GPE Action, %u", action)); return (AE_BAD_PARAMETER); } diff --git a/drivers/acpi/acpica/hwpci.c b/drivers/acpi/acpica/hwpci.c index 65bc3453a29c20c8c862a8a40983ead331d86291..0889a629505f857582c4f02bd65a8256cf3fe87e 100644 --- a/drivers/acpi/acpica/hwpci.c +++ b/drivers/acpi/acpica/hwpci.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/hwregs.c b/drivers/acpi/acpica/hwregs.c index f4e57503576b451a3929c085d63d8bfc2fe89d6e..083d6551f0e2b2db97020d6e0ecc4e9d7ed85211 100644 --- a/drivers/acpi/acpica/hwregs.c +++ b/drivers/acpi/acpica/hwregs.c @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,7 +44,6 @@ #include #include "accommon.h" -#include "acnamesp.h" #include "acevents.h" #define _COMPONENT ACPI_HARDWARE @@ -364,8 +363,7 @@ acpi_status acpi_hw_write_pm1_control(u32 pm1a_control, u32 pm1b_control) * DESCRIPTION: Read from the specified ACPI register * ******************************************************************************/ -acpi_status -acpi_hw_register_read(u32 register_id, u32 * return_value) +acpi_status acpi_hw_register_read(u32 register_id, u32 *return_value) { u32 value = 0; acpi_status status; @@ -485,7 +483,7 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value) &acpi_gbl_xpm1b_status); break; - case ACPI_REGISTER_PM1_ENABLE: /* PM1 A/B: 16-bit access */ + case ACPI_REGISTER_PM1_ENABLE: /* PM1 A/B: 16-bit access each */ status = acpi_hw_write_multiple(value, &acpi_gbl_xpm1a_enable, diff --git a/drivers/acpi/acpica/hwsleep.c b/drivers/acpi/acpica/hwsleep.c index 3fddde056a5e1774e2e208f2478ce07d53fa5bf5..e3828cc4361bfa46ed25d9b4374545758542b22c 100644 --- a/drivers/acpi/acpica/hwsleep.c +++ b/drivers/acpi/acpica/hwsleep.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -45,7 +45,6 @@ #include #include #include "accommon.h" -#include #define _COMPONENT ACPI_HARDWARE ACPI_MODULE_NAME("hwsleep") @@ -178,7 +177,7 @@ acpi_status acpi_hw_legacy_sleep(u8 sleep_state) * to still read the right value. Ideally, this block would go * away entirely. */ - acpi_os_stall(10000000); + acpi_os_stall(10 * ACPI_USEC_PER_SEC); status = acpi_hw_register_write(ACPI_REGISTER_PM1_CONTROL, sleep_enable_reg_info-> @@ -323,7 +322,8 @@ acpi_status acpi_hw_legacy_wake(u8 sleep_state) * and use it to determine whether the system is rebooting or * resuming. Clear WAK_STS for compatibility. */ - acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, 1); + (void)acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, + ACPI_CLEAR_STATUS); acpi_gbl_system_awake_and_running = TRUE; /* Enable power button */ diff --git a/drivers/acpi/acpica/hwtimer.c b/drivers/acpi/acpica/hwtimer.c index bfdce22f37988721385ff0d9f19131c2ff405a2d..0c1a8bbd05d6662949671d30ee1074da584da908 100644 --- a/drivers/acpi/acpica/hwtimer.c +++ b/drivers/acpi/acpica/hwtimer.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -176,10 +176,11 @@ acpi_get_timer_duration(u32 start_ticks, u32 end_ticks, u32 * time_elapsed) /* * Compute Duration (Requires a 64-bit multiply and divide): * - * time_elapsed = (delta_ticks * 1000000) / PM_TIMER_FREQUENCY; + * time_elapsed (microseconds) = + * (delta_ticks * ACPI_USEC_PER_SEC) / ACPI_PM_TIMER_FREQUENCY; */ - status = acpi_ut_short_divide(((u64) delta_ticks) * 1000000, - PM_TIMER_FREQUENCY, "ient, NULL); + status = acpi_ut_short_divide(((u64)delta_ticks) * ACPI_USEC_PER_SEC, + ACPI_PM_TIMER_FREQUENCY, "ient, NULL); *time_elapsed = (u32) quotient; return_ACPI_STATUS(status); diff --git a/drivers/acpi/acpica/hwvalid.c b/drivers/acpi/acpica/hwvalid.c index b6aae58299dc36dce839d7e74a4f17adcef36b98..eab70d58852a674fadb1881df67fbc0ad9717aa1 100644 --- a/drivers/acpi/acpica/hwvalid.c +++ b/drivers/acpi/acpica/hwvalid.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -135,7 +135,7 @@ acpi_hw_validate_io_request(acpi_io_address address, u32 bit_width) if ((bit_width != 8) && (bit_width != 16) && (bit_width != 32)) { ACPI_ERROR((AE_INFO, "Bad BitWidth parameter: %8.8X", bit_width)); - return AE_BAD_PARAMETER; + return (AE_BAD_PARAMETER); } port_info = acpi_protected_ports; @@ -234,11 +234,11 @@ acpi_status acpi_hw_read_port(acpi_io_address address, u32 *value, u32 width) status = acpi_hw_validate_io_request(address, width); if (ACPI_SUCCESS(status)) { status = acpi_os_read_port(address, value, width); - return status; + return (status); } if (status != AE_AML_ILLEGAL_ADDRESS) { - return status; + return (status); } /* @@ -253,7 +253,7 @@ acpi_status acpi_hw_read_port(acpi_io_address address, u32 *value, u32 width) if (acpi_hw_validate_io_request(address, 8) == AE_OK) { status = acpi_os_read_port(address, &one_byte, 8); if (ACPI_FAILURE(status)) { - return status; + return (status); } *value |= (one_byte << i); @@ -262,7 +262,7 @@ acpi_status acpi_hw_read_port(acpi_io_address address, u32 *value, u32 width) address++; } - return AE_OK; + return (AE_OK); } /****************************************************************************** @@ -297,11 +297,11 @@ acpi_status acpi_hw_write_port(acpi_io_address address, u32 value, u32 width) status = acpi_hw_validate_io_request(address, width); if (ACPI_SUCCESS(status)) { status = acpi_os_write_port(address, value, width); - return status; + return (status); } if (status != AE_AML_ILLEGAL_ADDRESS) { - return status; + return (status); } /* @@ -317,12 +317,12 @@ acpi_status acpi_hw_write_port(acpi_io_address address, u32 value, u32 width) status = acpi_os_write_port(address, (value >> i) & 0xFF, 8); if (ACPI_FAILURE(status)) { - return status; + return (status); } } address++; } - return AE_OK; + return (AE_OK); } diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c index 05a154c3c9acde9b9d691970af4de093049c10ab..04c2e16f2c0a6ef86ab734cd309cfb1ce41d49db 100644 --- a/drivers/acpi/acpica/hwxface.c +++ b/drivers/acpi/acpica/hwxface.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -80,10 +80,10 @@ acpi_status acpi_reset(void) if (reset_reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) { /* - * For I/O space, write directly to the OSL. This - * bypasses the port validation mechanism, which may - * block a valid write to the reset register. Spec - * section 4.7.3.6 requires register width to be 8. + * For I/O space, write directly to the OSL. This bypasses the port + * validation mechanism, which may block a valid write to the reset + * register. + * Spec section 4.7.3.6 requires register width to be 8. */ status = acpi_os_write_port((acpi_io_address) reset_reg->address, @@ -333,7 +333,7 @@ ACPI_EXPORT_SYMBOL(acpi_read_bit_register) * FUNCTION: acpi_write_bit_register * * PARAMETERS: register_id - ID of ACPI Bit Register to access - * Value - Value to write to the register, in bit + * value - Value to write to the register, in bit * position zero. The bit is automatically * shifted to the correct position. * @@ -440,17 +440,41 @@ ACPI_EXPORT_SYMBOL(acpi_write_bit_register) * *sleep_type_a - Where SLP_TYPa is returned * *sleep_type_b - Where SLP_TYPb is returned * - * RETURN: status - ACPI status + * RETURN: Status + * + * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested + * sleep state via the appropriate \_Sx object. + * + * The sleep state package returned from the corresponding \_Sx_ object + * must contain at least one integer. + * + * March 2005: + * Added support for a package that contains two integers. This + * goes against the ACPI specification which defines this object as a + * package with one encoded DWORD integer. However, existing practice + * by many BIOS vendors is to return a package with 2 or more integer + * elements, at least one per sleep type (A/B). * - * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested sleep - * state. + * January 2013: + * Therefore, we must be prepared to accept a package with either a + * single integer or multiple integers. + * + * The single integer DWORD format is as follows: + * BYTE 0 - Value for the PM1A SLP_TYP register + * BYTE 1 - Value for the PM1B SLP_TYP register + * BYTE 2-3 - Reserved + * + * The dual integer format is as follows: + * Integer 0 - Value for the PM1A SLP_TYP register + * Integer 1 - Value for the PM1A SLP_TYP register * ******************************************************************************/ acpi_status acpi_get_sleep_type_data(u8 sleep_state, u8 *sleep_type_a, u8 *sleep_type_b) { - acpi_status status = AE_OK; + acpi_status status; struct acpi_evaluate_info *info; + union acpi_operand_object **elements; ACPI_FUNCTION_TRACE(acpi_get_sleep_type_data); @@ -467,18 +491,14 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 *sleep_type_a, u8 *sleep_type_b) return_ACPI_STATUS(AE_NO_MEMORY); } + /* + * Evaluate the \_Sx namespace object containing the register values + * for this state + */ info->pathname = ACPI_CAST_PTR(char, acpi_gbl_sleep_state_names[sleep_state]); - - /* Evaluate the namespace object containing the values for this state */ - status = acpi_ns_evaluate(info); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "%s while evaluating SleepState [%s]\n", - acpi_format_exception(status), - info->pathname)); - goto cleanup; } @@ -487,64 +507,67 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 *sleep_type_a, u8 *sleep_type_b) if (!info->return_object) { ACPI_ERROR((AE_INFO, "No Sleep State object returned from [%s]", info->pathname)); - status = AE_NOT_EXIST; + status = AE_AML_NO_RETURN_VALUE; + goto cleanup; } - /* It must be of type Package */ + /* Return object must be of type Package */ - else if (info->return_object->common.type != ACPI_TYPE_PACKAGE) { + if (info->return_object->common.type != ACPI_TYPE_PACKAGE) { ACPI_ERROR((AE_INFO, "Sleep State return object is not a Package")); status = AE_AML_OPERAND_TYPE; + goto cleanup1; } /* - * The package must have at least two elements. NOTE (March 2005): This - * goes against the current ACPI spec which defines this object as a - * package with one encoded DWORD element. However, existing practice - * by BIOS vendors seems to be to have 2 or more elements, at least - * one per sleep type (A/B). + * Any warnings about the package length or the object types have + * already been issued by the predefined name module -- there is no + * need to repeat them here. */ - else if (info->return_object->package.count < 2) { - ACPI_ERROR((AE_INFO, - "Sleep State return package does not have at least two elements")); - status = AE_AML_NO_OPERAND; - } + elements = info->return_object->package.elements; + switch (info->return_object->package.count) { + case 0: + status = AE_AML_PACKAGE_LIMIT; + break; + + case 1: + if (elements[0]->common.type != ACPI_TYPE_INTEGER) { + status = AE_AML_OPERAND_TYPE; + break; + } - /* The first two elements must both be of type Integer */ + /* A valid _Sx_ package with one integer */ - else if (((info->return_object->package.elements[0])->common.type - != ACPI_TYPE_INTEGER) || - ((info->return_object->package.elements[1])->common.type - != ACPI_TYPE_INTEGER)) { - ACPI_ERROR((AE_INFO, - "Sleep State return package elements are not both Integers " - "(%s, %s)", - acpi_ut_get_object_type_name(info->return_object-> - package.elements[0]), - acpi_ut_get_object_type_name(info->return_object-> - package.elements[1]))); - status = AE_AML_OPERAND_TYPE; - } else { - /* Valid _Sx_ package size, type, and value */ + *sleep_type_a = (u8)elements[0]->integer.value; + *sleep_type_b = (u8)(elements[0]->integer.value >> 8); + break; - *sleep_type_a = (u8) - (info->return_object->package.elements[0])->integer.value; - *sleep_type_b = (u8) - (info->return_object->package.elements[1])->integer.value; - } + case 2: + default: + if ((elements[0]->common.type != ACPI_TYPE_INTEGER) || + (elements[1]->common.type != ACPI_TYPE_INTEGER)) { + status = AE_AML_OPERAND_TYPE; + break; + } - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "While evaluating SleepState [%s], bad Sleep object %p type %s", - info->pathname, info->return_object, - acpi_ut_get_object_type_name(info-> - return_object))); + /* A valid _Sx_ package with two integers */ + + *sleep_type_a = (u8)elements[0]->integer.value; + *sleep_type_b = (u8)elements[1]->integer.value; + break; } + cleanup1: acpi_ut_remove_reference(info->return_object); cleanup: + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "While evaluating Sleep State [%s]", + info->pathname)); + } + ACPI_FREE(info); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/hwxfsleep.c b/drivers/acpi/acpica/hwxfsleep.c index ae443fe2ebf6c762330a022d5a845076051f07ae..35eebdac0f9d1e02976d382376005abbe4a870a5 100644 --- a/drivers/acpi/acpica/hwxfsleep.c +++ b/drivers/acpi/acpica/hwxfsleep.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -41,9 +41,9 @@ * POSSIBILITY OF SUCH DAMAGES. */ +#include #include #include "accommon.h" -#include #define _COMPONENT ACPI_HARDWARE ACPI_MODULE_NAME("hwxfsleep") @@ -207,7 +207,7 @@ acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void) (u32)acpi_gbl_FADT.s4_bios_request, 8); do { - acpi_os_stall(1000); + acpi_os_stall(ACPI_USEC_PER_MSEC); status = acpi_read_bit_register(ACPI_BITREG_WAKE_STATUS, &in_value); if (ACPI_FAILURE(status)) { @@ -350,7 +350,7 @@ ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep) * * RETURN: Status * - * DESCRIPTION: Enter a system sleep state (see ACPI 2.0 spec p 231) + * DESCRIPTION: Enter a system sleep state * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED * ******************************************************************************/ @@ -382,8 +382,9 @@ ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state) * RETURN: Status * * DESCRIPTION: Perform the first state of OS-independent ACPI cleanup after a - * sleep. - * Called with interrupts DISABLED. + * sleep. Called with interrupts DISABLED. + * We break wake/resume into 2 stages so that OSPM can handle + * various OS-specific tasks between the two steps. * ******************************************************************************/ acpi_status acpi_leave_sleep_state_prep(u8 sleep_state) diff --git a/drivers/acpi/acpica/nsaccess.c b/drivers/acpi/acpica/nsaccess.c index d70eaf39dfdfd40cff45637ff5d09b637f3a2ad6..8769cf83b044ff704db113a4ef7ffc8a5f78fbc0 100644 --- a/drivers/acpi/acpica/nsaccess.c +++ b/drivers/acpi/acpica/nsaccess.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nsalloc.c b/drivers/acpi/acpica/nsalloc.c index 15143c44f5e5f3385b9cbecd8a97d61db1024e4e..243737363fb8ea51c80f77a16908659a29271a48 100644 --- a/drivers/acpi/acpica/nsalloc.c +++ b/drivers/acpi/acpica/nsalloc.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nsdump.c b/drivers/acpi/acpica/nsdump.c index 924b3c71473a6c75adf82b239fab1dcd8340790d..ce6e9732620523ba36e1a474d76dddfcf03005d9 100644 --- a/drivers/acpi/acpica/nsdump.c +++ b/drivers/acpi/acpica/nsdump.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,6 +44,7 @@ #include #include "accommon.h" #include "acnamesp.h" +#include #define _COMPONENT ACPI_NAMESPACE ACPI_MODULE_NAME("nsdump") @@ -77,8 +78,9 @@ void acpi_ns_print_pathname(u32 num_segments, char *pathname) ACPI_FUNCTION_NAME(ns_print_pathname); - if (!(acpi_dbg_level & ACPI_LV_NAMES) - || !(acpi_dbg_layer & ACPI_NAMESPACE)) { + /* Check if debug output enabled */ + + if (!ACPI_IS_DEBUG_ENABLED(ACPI_LV_NAMES, ACPI_NAMESPACE)) { return; } @@ -127,7 +129,7 @@ acpi_ns_dump_pathname(acpi_handle handle, char *msg, u32 level, u32 component) /* Do this only if the requested debug level and component are enabled */ - if (!(acpi_dbg_level & level) || !(acpi_dbg_layer & component)) { + if (!ACPI_IS_DEBUG_ENABLED(level, component)) { return_VOID; } @@ -729,5 +731,5 @@ void acpi_ns_dump_tables(acpi_handle search_base, u32 max_depth) ACPI_OWNER_ID_MAX, search_handle); return_VOID; } -#endif /* _ACPI_ASL_COMPILER */ -#endif /* defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) */ +#endif +#endif diff --git a/drivers/acpi/acpica/nsdumpdv.c b/drivers/acpi/acpica/nsdumpdv.c index 944d4c8d94386747337588938821035dfca79909..409ae80824d1e5a12d030bc67d79d7ec51679cc7 100644 --- a/drivers/acpi/acpica/nsdumpdv.c +++ b/drivers/acpi/acpica/nsdumpdv.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -42,7 +42,6 @@ */ #include -#include "accommon.h" /* TBD: This entire module is apparently obsolete and should be removed */ diff --git a/drivers/acpi/acpica/nseval.c b/drivers/acpi/acpica/nseval.c index 69074be498e886a50ed75c1fa82d9bcb0f96e7f0..1538f3eb2a8fdfa970ec1ce6cf8117726a81d21a 100644 --- a/drivers/acpi/acpica/nseval.c +++ b/drivers/acpi/acpica/nseval.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nsinit.c b/drivers/acpi/acpica/nsinit.c index 4328e2adfeb9e9e5e08fb4ce920a4aea511b3da0..2a431ec50a2543efa1383f573c83799b8f92c6a1 100644 --- a/drivers/acpi/acpica/nsinit.c +++ b/drivers/acpi/acpica/nsinit.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -46,7 +46,6 @@ #include "acnamesp.h" #include "acdispat.h" #include "acinterp.h" -#include #define _COMPONENT ACPI_NAMESPACE ACPI_MODULE_NAME("nsinit") @@ -87,7 +86,7 @@ acpi_status acpi_ns_initialize_objects(void) ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "**** Starting initialization of namespace objects ****\n")); ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, - "Completing Region/Field/Buffer/Package initialization:")); + "Completing Region/Field/Buffer/Package initialization:\n")); /* Set all init info to zero */ @@ -103,7 +102,7 @@ acpi_status acpi_ns_initialize_objects(void) } ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, - "\nInitialized %u/%u Regions %u/%u Fields %u/%u " + " Initialized %u/%u Regions %u/%u Fields %u/%u " "Buffers %u/%u Packages (%u nodes)\n", info.op_region_init, info.op_region_count, info.field_init, info.field_count, @@ -150,7 +149,7 @@ acpi_status acpi_ns_initialize_devices(void) ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, "Initializing Device/Processor/Thermal objects " - "by executing _INI methods:")); + "and executing _INI/_STA methods:\n")); /* Tree analysis: find all subtrees that contain _INI methods */ @@ -208,7 +207,7 @@ acpi_status acpi_ns_initialize_devices(void) } ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, - "\nExecuted %u _INI methods requiring %u _STA executions " + " Executed %u _INI methods requiring %u _STA executions " "(examined %u objects)\n", info.num_INI, info.num_STA, info.device_count)); @@ -349,14 +348,6 @@ acpi_ns_init_one_object(acpi_handle obj_handle, acpi_ut_get_type_name(type))); } - /* - * Print a dot for each object unless we are going to print the entire - * pathname - */ - if (!(acpi_dbg_level & ACPI_LV_INIT_NAMES)) { - ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, ".")); - } - /* * We ignore errors from above, and always return OK, since we don't want * to abort the walk on any single error. @@ -572,20 +563,10 @@ acpi_ns_init_one_device(acpi_handle obj_handle, info->parameters = NULL; info->flags = ACPI_IGNORE_RETURN_VALUE; - /* - * Some hardware relies on this being executed as atomically - * as possible (without an NMI being received in the middle of - * this) - so disable NMIs and initialize the device: - */ status = acpi_ns_evaluate(info); if (ACPI_SUCCESS(status)) { walk_info->num_INI++; - - if ((acpi_dbg_level <= ACPI_LV_ALL_EXCEPTIONS) && - (!(acpi_dbg_level & ACPI_LV_INFO))) { - ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, ".")); - } } #ifdef ACPI_DEBUG_OUTPUT else if (status != AE_NOT_FOUND) { diff --git a/drivers/acpi/acpica/nsload.c b/drivers/acpi/acpica/nsload.c index 911f99127b991fb23a0069efb98293ab45e39b43..0a7badc3179f089d8f09b886547961f91e16b8d6 100644 --- a/drivers/acpi/acpica/nsload.c +++ b/drivers/acpi/acpica/nsload.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nsnames.c b/drivers/acpi/acpica/nsnames.c index 55a175eadcc31b1a7f132f4c1923c3a01aa253b5..90a0380fb8a04b51fd508817247531303825d18a 100644 --- a/drivers/acpi/acpica/nsnames.c +++ b/drivers/acpi/acpica/nsnames.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -126,7 +126,8 @@ acpi_ns_build_external_path(struct acpi_namespace_node *node, * the node, In external format (name segments separated by path * separators.) * - * DESCRIPTION: Used for debug printing in acpi_ns_search_table(). + * DESCRIPTION: Used to obtain the full pathname to a namespace node, usually + * for error and debug statements. * ******************************************************************************/ diff --git a/drivers/acpi/acpica/nsobject.c b/drivers/acpi/acpica/nsobject.c index e69f7fa2579d2443fcbc99461661c51d6e104da5..7a736f4d1fd8184953a023ae70cbc95c56f27024 100644 --- a/drivers/acpi/acpica/nsobject.c +++ b/drivers/acpi/acpica/nsobject.c @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nsparse.c b/drivers/acpi/acpica/nsparse.c index 233f756d5cfa7d5fdd9e2dc5aa36ea82eec3a410..35dde8151c0d14fdec6cdd68eb55c69506d2b1fb 100644 --- a/drivers/acpi/acpica/nsparse.c +++ b/drivers/acpi/acpica/nsparse.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c index 2419f417ea33220f5ee04212866499a476b6ed51..224c3005340112add4471f37c7b676247dfdfb34 100644 --- a/drivers/acpi/acpica/nspredef.c +++ b/drivers/acpi/acpica/nspredef.c @@ -1,12 +1,11 @@ /****************************************************************************** * * Module Name: nspredef - Validation of ACPI predefined methods and objects - * $Revision: 1.1 $ * *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -73,27 +72,6 @@ ACPI_MODULE_NAME("nspredef") * ******************************************************************************/ /* Local prototypes */ -static acpi_status -acpi_ns_check_package(struct acpi_predefined_data *data, - union acpi_operand_object **return_object_ptr); - -static acpi_status -acpi_ns_check_package_list(struct acpi_predefined_data *data, - const union acpi_predefined_info *package, - union acpi_operand_object **elements, u32 count); - -static acpi_status -acpi_ns_check_package_elements(struct acpi_predefined_data *data, - union acpi_operand_object **elements, - u8 type1, - u32 count1, - u8 type2, u32 count2, u32 start_index); - -static acpi_status -acpi_ns_check_object_type(struct acpi_predefined_data *data, - union acpi_operand_object **return_object_ptr, - u32 expected_btypes, u32 package_index); - static acpi_status acpi_ns_check_reference(struct acpi_predefined_data *data, union acpi_operand_object *return_object); @@ -148,7 +126,7 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node, pathname = acpi_ns_get_external_pathname(node); if (!pathname) { - return AE_OK; /* Could not get pathname, ignore */ + return (AE_OK); /* Could not get pathname, ignore */ } /* @@ -406,564 +384,6 @@ const union acpi_predefined_info *acpi_ns_check_for_predefined_name(struct return (NULL); /* Not found */ } -/******************************************************************************* - * - * FUNCTION: acpi_ns_check_package - * - * PARAMETERS: data - Pointer to validation data structure - * return_object_ptr - Pointer to the object returned from the - * evaluation of a method or object - * - * RETURN: Status - * - * DESCRIPTION: Check a returned package object for the correct count and - * correct type of all sub-objects. - * - ******************************************************************************/ - -static acpi_status -acpi_ns_check_package(struct acpi_predefined_data *data, - union acpi_operand_object **return_object_ptr) -{ - union acpi_operand_object *return_object = *return_object_ptr; - const union acpi_predefined_info *package; - union acpi_operand_object **elements; - acpi_status status = AE_OK; - u32 expected_count; - u32 count; - u32 i; - - ACPI_FUNCTION_NAME(ns_check_package); - - /* The package info for this name is in the next table entry */ - - package = data->predefined + 1; - - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, - "%s Validating return Package of Type %X, Count %X\n", - data->pathname, package->ret_info.type, - return_object->package.count)); - - /* - * For variable-length Packages, we can safely remove all embedded - * and trailing NULL package elements - */ - acpi_ns_remove_null_elements(data, package->ret_info.type, - return_object); - - /* Extract package count and elements array */ - - elements = return_object->package.elements; - count = return_object->package.count; - - /* The package must have at least one element, else invalid */ - - if (!count) { - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, - "Return Package has no elements (empty)")); - - return (AE_AML_OPERAND_VALUE); - } - - /* - * Decode the type of the expected package contents - * - * PTYPE1 packages contain no subpackages - * PTYPE2 packages contain sub-packages - */ - switch (package->ret_info.type) { - case ACPI_PTYPE1_FIXED: - - /* - * The package count is fixed and there are no sub-packages - * - * If package is too small, exit. - * If package is larger than expected, issue warning but continue - */ - expected_count = - package->ret_info.count1 + package->ret_info.count2; - if (count < expected_count) { - goto package_too_small; - } else if (count > expected_count) { - ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, - "%s: Return Package is larger than needed - " - "found %u, expected %u\n", - data->pathname, count, - expected_count)); - } - - /* Validate all elements of the returned package */ - - status = acpi_ns_check_package_elements(data, elements, - package->ret_info. - object_type1, - package->ret_info. - count1, - package->ret_info. - object_type2, - package->ret_info. - count2, 0); - break; - - case ACPI_PTYPE1_VAR: - - /* - * The package count is variable, there are no sub-packages, and all - * elements must be of the same type - */ - for (i = 0; i < count; i++) { - status = acpi_ns_check_object_type(data, elements, - package->ret_info. - object_type1, i); - if (ACPI_FAILURE(status)) { - return (status); - } - elements++; - } - break; - - case ACPI_PTYPE1_OPTION: - - /* - * The package count is variable, there are no sub-packages. There are - * a fixed number of required elements, and a variable number of - * optional elements. - * - * Check if package is at least as large as the minimum required - */ - expected_count = package->ret_info3.count; - if (count < expected_count) { - goto package_too_small; - } - - /* Variable number of sub-objects */ - - for (i = 0; i < count; i++) { - if (i < package->ret_info3.count) { - - /* These are the required package elements (0, 1, or 2) */ - - status = - acpi_ns_check_object_type(data, elements, - package-> - ret_info3. - object_type[i], - i); - if (ACPI_FAILURE(status)) { - return (status); - } - } else { - /* These are the optional package elements */ - - status = - acpi_ns_check_object_type(data, elements, - package-> - ret_info3. - tail_object_type, - i); - if (ACPI_FAILURE(status)) { - return (status); - } - } - elements++; - } - break; - - case ACPI_PTYPE2_REV_FIXED: - - /* First element is the (Integer) revision */ - - status = acpi_ns_check_object_type(data, elements, - ACPI_RTYPE_INTEGER, 0); - if (ACPI_FAILURE(status)) { - return (status); - } - - elements++; - count--; - - /* Examine the sub-packages */ - - status = - acpi_ns_check_package_list(data, package, elements, count); - break; - - case ACPI_PTYPE2_PKG_COUNT: - - /* First element is the (Integer) count of sub-packages to follow */ - - status = acpi_ns_check_object_type(data, elements, - ACPI_RTYPE_INTEGER, 0); - if (ACPI_FAILURE(status)) { - return (status); - } - - /* - * Count cannot be larger than the parent package length, but allow it - * to be smaller. The >= accounts for the Integer above. - */ - expected_count = (u32) (*elements)->integer.value; - if (expected_count >= count) { - goto package_too_small; - } - - count = expected_count; - elements++; - - /* Examine the sub-packages */ - - status = - acpi_ns_check_package_list(data, package, elements, count); - break; - - case ACPI_PTYPE2: - case ACPI_PTYPE2_FIXED: - case ACPI_PTYPE2_MIN: - case ACPI_PTYPE2_COUNT: - case ACPI_PTYPE2_FIX_VAR: - - /* - * These types all return a single Package that consists of a - * variable number of sub-Packages. - * - * First, ensure that the first element is a sub-Package. If not, - * the BIOS may have incorrectly returned the object as a single - * package instead of a Package of Packages (a common error if - * there is only one entry). We may be able to repair this by - * wrapping the returned Package with a new outer Package. - */ - if (*elements - && ((*elements)->common.type != ACPI_TYPE_PACKAGE)) { - - /* Create the new outer package and populate it */ - - status = - acpi_ns_wrap_with_package(data, return_object, - return_object_ptr); - if (ACPI_FAILURE(status)) { - return (status); - } - - /* Update locals to point to the new package (of 1 element) */ - - return_object = *return_object_ptr; - elements = return_object->package.elements; - count = 1; - } - - /* Examine the sub-packages */ - - status = - acpi_ns_check_package_list(data, package, elements, count); - break; - - default: - - /* Should not get here if predefined info table is correct */ - - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, - "Invalid internal return type in table entry: %X", - package->ret_info.type)); - - return (AE_AML_INTERNAL); - } - - return (status); - -package_too_small: - - /* Error exit for the case with an incorrect package count */ - - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, - "Return Package is too small - found %u elements, expected %u", - count, expected_count)); - - return (AE_AML_OPERAND_VALUE); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_check_package_list - * - * PARAMETERS: data - Pointer to validation data structure - * package - Pointer to package-specific info for method - * elements - Element list of parent package. All elements - * of this list should be of type Package. - * count - Count of subpackages - * - * RETURN: Status - * - * DESCRIPTION: Examine a list of subpackages - * - ******************************************************************************/ - -static acpi_status -acpi_ns_check_package_list(struct acpi_predefined_data *data, - const union acpi_predefined_info *package, - union acpi_operand_object **elements, u32 count) -{ - union acpi_operand_object *sub_package; - union acpi_operand_object **sub_elements; - acpi_status status; - u32 expected_count; - u32 i; - u32 j; - - /* - * Validate each sub-Package in the parent Package - * - * NOTE: assumes list of sub-packages contains no NULL elements. - * Any NULL elements should have been removed by earlier call - * to acpi_ns_remove_null_elements. - */ - for (i = 0; i < count; i++) { - sub_package = *elements; - sub_elements = sub_package->package.elements; - data->parent_package = sub_package; - - /* Each sub-object must be of type Package */ - - status = acpi_ns_check_object_type(data, &sub_package, - ACPI_RTYPE_PACKAGE, i); - if (ACPI_FAILURE(status)) { - return (status); - } - - /* Examine the different types of expected sub-packages */ - - data->parent_package = sub_package; - switch (package->ret_info.type) { - case ACPI_PTYPE2: - case ACPI_PTYPE2_PKG_COUNT: - case ACPI_PTYPE2_REV_FIXED: - - /* Each subpackage has a fixed number of elements */ - - expected_count = - package->ret_info.count1 + package->ret_info.count2; - if (sub_package->package.count < expected_count) { - goto package_too_small; - } - - status = - acpi_ns_check_package_elements(data, sub_elements, - package->ret_info. - object_type1, - package->ret_info. - count1, - package->ret_info. - object_type2, - package->ret_info. - count2, 0); - if (ACPI_FAILURE(status)) { - return (status); - } - break; - - case ACPI_PTYPE2_FIX_VAR: - /* - * Each subpackage has a fixed number of elements and an - * optional element - */ - expected_count = - package->ret_info.count1 + package->ret_info.count2; - if (sub_package->package.count < expected_count) { - goto package_too_small; - } - - status = - acpi_ns_check_package_elements(data, sub_elements, - package->ret_info. - object_type1, - package->ret_info. - count1, - package->ret_info. - object_type2, - sub_package->package. - count - - package->ret_info. - count1, 0); - if (ACPI_FAILURE(status)) { - return (status); - } - break; - - case ACPI_PTYPE2_FIXED: - - /* Each sub-package has a fixed length */ - - expected_count = package->ret_info2.count; - if (sub_package->package.count < expected_count) { - goto package_too_small; - } - - /* Check the type of each sub-package element */ - - for (j = 0; j < expected_count; j++) { - status = - acpi_ns_check_object_type(data, - &sub_elements[j], - package-> - ret_info2. - object_type[j], - j); - if (ACPI_FAILURE(status)) { - return (status); - } - } - break; - - case ACPI_PTYPE2_MIN: - - /* Each sub-package has a variable but minimum length */ - - expected_count = package->ret_info.count1; - if (sub_package->package.count < expected_count) { - goto package_too_small; - } - - /* Check the type of each sub-package element */ - - status = - acpi_ns_check_package_elements(data, sub_elements, - package->ret_info. - object_type1, - sub_package->package. - count, 0, 0, 0); - if (ACPI_FAILURE(status)) { - return (status); - } - break; - - case ACPI_PTYPE2_COUNT: - - /* - * First element is the (Integer) count of elements, including - * the count field (the ACPI name is num_elements) - */ - status = acpi_ns_check_object_type(data, sub_elements, - ACPI_RTYPE_INTEGER, - 0); - if (ACPI_FAILURE(status)) { - return (status); - } - - /* - * Make sure package is large enough for the Count and is - * is as large as the minimum size - */ - expected_count = (u32)(*sub_elements)->integer.value; - if (sub_package->package.count < expected_count) { - goto package_too_small; - } - if (sub_package->package.count < - package->ret_info.count1) { - expected_count = package->ret_info.count1; - goto package_too_small; - } - if (expected_count == 0) { - /* - * Either the num_entries element was originally zero or it was - * a NULL element and repaired to an Integer of value zero. - * In either case, repair it by setting num_entries to be the - * actual size of the subpackage. - */ - expected_count = sub_package->package.count; - (*sub_elements)->integer.value = expected_count; - } - - /* Check the type of each sub-package element */ - - status = - acpi_ns_check_package_elements(data, - (sub_elements + 1), - package->ret_info. - object_type1, - (expected_count - 1), - 0, 0, 1); - if (ACPI_FAILURE(status)) { - return (status); - } - break; - - default: /* Should not get here, type was validated by caller */ - - return (AE_AML_INTERNAL); - } - - elements++; - } - - return (AE_OK); - -package_too_small: - - /* The sub-package count was smaller than required */ - - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, - "Return Sub-Package[%u] is too small - found %u elements, expected %u", - i, sub_package->package.count, expected_count)); - - return (AE_AML_OPERAND_VALUE); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_check_package_elements - * - * PARAMETERS: data - Pointer to validation data structure - * elements - Pointer to the package elements array - * type1 - Object type for first group - * count1 - Count for first group - * type2 - Object type for second group - * count2 - Count for second group - * start_index - Start of the first group of elements - * - * RETURN: Status - * - * DESCRIPTION: Check that all elements of a package are of the correct object - * type. Supports up to two groups of different object types. - * - ******************************************************************************/ - -static acpi_status -acpi_ns_check_package_elements(struct acpi_predefined_data *data, - union acpi_operand_object **elements, - u8 type1, - u32 count1, - u8 type2, u32 count2, u32 start_index) -{ - union acpi_operand_object **this_element = elements; - acpi_status status; - u32 i; - - /* - * Up to two groups of package elements are supported by the data - * structure. All elements in each group must be of the same type. - * The second group can have a count of zero. - */ - for (i = 0; i < count1; i++) { - status = acpi_ns_check_object_type(data, this_element, - type1, i + start_index); - if (ACPI_FAILURE(status)) { - return (status); - } - this_element++; - } - - for (i = 0; i < count2; i++) { - status = acpi_ns_check_object_type(data, this_element, - type2, - (i + count1 + start_index)); - if (ACPI_FAILURE(status)) { - return (status); - } - this_element++; - } - - return (AE_OK); -} - /******************************************************************************* * * FUNCTION: acpi_ns_check_object_type @@ -983,7 +403,7 @@ acpi_ns_check_package_elements(struct acpi_predefined_data *data, * ******************************************************************************/ -static acpi_status +acpi_status acpi_ns_check_object_type(struct acpi_predefined_data *data, union acpi_operand_object **return_object_ptr, u32 expected_btypes, u32 package_index) diff --git a/drivers/acpi/acpica/nsprepkg.c b/drivers/acpi/acpica/nsprepkg.c new file mode 100644 index 0000000000000000000000000000000000000000..a40155467d2e2883acd82b7fe8feaab8e121fc31 --- /dev/null +++ b/drivers/acpi/acpica/nsprepkg.c @@ -0,0 +1,621 @@ +/****************************************************************************** + * + * Module Name: nsprepkg - Validation of package objects for predefined names + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2013, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include "accommon.h" +#include "acnamesp.h" +#include "acpredef.h" + +#define _COMPONENT ACPI_NAMESPACE +ACPI_MODULE_NAME("nsprepkg") + +/* Local prototypes */ +static acpi_status +acpi_ns_check_package_list(struct acpi_predefined_data *data, + const union acpi_predefined_info *package, + union acpi_operand_object **elements, u32 count); + +static acpi_status +acpi_ns_check_package_elements(struct acpi_predefined_data *data, + union acpi_operand_object **elements, + u8 type1, + u32 count1, + u8 type2, u32 count2, u32 start_index); + +/******************************************************************************* + * + * FUNCTION: acpi_ns_check_package + * + * PARAMETERS: data - Pointer to validation data structure + * return_object_ptr - Pointer to the object returned from the + * evaluation of a method or object + * + * RETURN: Status + * + * DESCRIPTION: Check a returned package object for the correct count and + * correct type of all sub-objects. + * + ******************************************************************************/ + +acpi_status +acpi_ns_check_package(struct acpi_predefined_data *data, + union acpi_operand_object **return_object_ptr) +{ + union acpi_operand_object *return_object = *return_object_ptr; + const union acpi_predefined_info *package; + union acpi_operand_object **elements; + acpi_status status = AE_OK; + u32 expected_count; + u32 count; + u32 i; + + ACPI_FUNCTION_NAME(ns_check_package); + + /* The package info for this name is in the next table entry */ + + package = data->predefined + 1; + + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, + "%s Validating return Package of Type %X, Count %X\n", + data->pathname, package->ret_info.type, + return_object->package.count)); + + /* + * For variable-length Packages, we can safely remove all embedded + * and trailing NULL package elements + */ + acpi_ns_remove_null_elements(data, package->ret_info.type, + return_object); + + /* Extract package count and elements array */ + + elements = return_object->package.elements; + count = return_object->package.count; + + /* The package must have at least one element, else invalid */ + + if (!count) { + ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, + "Return Package has no elements (empty)")); + + return (AE_AML_OPERAND_VALUE); + } + + /* + * Decode the type of the expected package contents + * + * PTYPE1 packages contain no subpackages + * PTYPE2 packages contain sub-packages + */ + switch (package->ret_info.type) { + case ACPI_PTYPE1_FIXED: + + /* + * The package count is fixed and there are no sub-packages + * + * If package is too small, exit. + * If package is larger than expected, issue warning but continue + */ + expected_count = + package->ret_info.count1 + package->ret_info.count2; + if (count < expected_count) { + goto package_too_small; + } else if (count > expected_count) { + ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, + "%s: Return Package is larger than needed - " + "found %u, expected %u\n", + data->pathname, count, + expected_count)); + } + + /* Validate all elements of the returned package */ + + status = acpi_ns_check_package_elements(data, elements, + package->ret_info. + object_type1, + package->ret_info. + count1, + package->ret_info. + object_type2, + package->ret_info. + count2, 0); + break; + + case ACPI_PTYPE1_VAR: + + /* + * The package count is variable, there are no sub-packages, and all + * elements must be of the same type + */ + for (i = 0; i < count; i++) { + status = acpi_ns_check_object_type(data, elements, + package->ret_info. + object_type1, i); + if (ACPI_FAILURE(status)) { + return (status); + } + elements++; + } + break; + + case ACPI_PTYPE1_OPTION: + + /* + * The package count is variable, there are no sub-packages. There are + * a fixed number of required elements, and a variable number of + * optional elements. + * + * Check if package is at least as large as the minimum required + */ + expected_count = package->ret_info3.count; + if (count < expected_count) { + goto package_too_small; + } + + /* Variable number of sub-objects */ + + for (i = 0; i < count; i++) { + if (i < package->ret_info3.count) { + + /* These are the required package elements (0, 1, or 2) */ + + status = + acpi_ns_check_object_type(data, elements, + package-> + ret_info3. + object_type[i], + i); + if (ACPI_FAILURE(status)) { + return (status); + } + } else { + /* These are the optional package elements */ + + status = + acpi_ns_check_object_type(data, elements, + package-> + ret_info3. + tail_object_type, + i); + if (ACPI_FAILURE(status)) { + return (status); + } + } + elements++; + } + break; + + case ACPI_PTYPE2_REV_FIXED: + + /* First element is the (Integer) revision */ + + status = acpi_ns_check_object_type(data, elements, + ACPI_RTYPE_INTEGER, 0); + if (ACPI_FAILURE(status)) { + return (status); + } + + elements++; + count--; + + /* Examine the sub-packages */ + + status = + acpi_ns_check_package_list(data, package, elements, count); + break; + + case ACPI_PTYPE2_PKG_COUNT: + + /* First element is the (Integer) count of sub-packages to follow */ + + status = acpi_ns_check_object_type(data, elements, + ACPI_RTYPE_INTEGER, 0); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* + * Count cannot be larger than the parent package length, but allow it + * to be smaller. The >= accounts for the Integer above. + */ + expected_count = (u32)(*elements)->integer.value; + if (expected_count >= count) { + goto package_too_small; + } + + count = expected_count; + elements++; + + /* Examine the sub-packages */ + + status = + acpi_ns_check_package_list(data, package, elements, count); + break; + + case ACPI_PTYPE2: + case ACPI_PTYPE2_FIXED: + case ACPI_PTYPE2_MIN: + case ACPI_PTYPE2_COUNT: + case ACPI_PTYPE2_FIX_VAR: + + /* + * These types all return a single Package that consists of a + * variable number of sub-Packages. + * + * First, ensure that the first element is a sub-Package. If not, + * the BIOS may have incorrectly returned the object as a single + * package instead of a Package of Packages (a common error if + * there is only one entry). We may be able to repair this by + * wrapping the returned Package with a new outer Package. + */ + if (*elements + && ((*elements)->common.type != ACPI_TYPE_PACKAGE)) { + + /* Create the new outer package and populate it */ + + status = + acpi_ns_wrap_with_package(data, return_object, + return_object_ptr); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* Update locals to point to the new package (of 1 element) */ + + return_object = *return_object_ptr; + elements = return_object->package.elements; + count = 1; + } + + /* Examine the sub-packages */ + + status = + acpi_ns_check_package_list(data, package, elements, count); + break; + + default: + + /* Should not get here if predefined info table is correct */ + + ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, + "Invalid internal return type in table entry: %X", + package->ret_info.type)); + + return (AE_AML_INTERNAL); + } + + return (status); + + package_too_small: + + /* Error exit for the case with an incorrect package count */ + + ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, + "Return Package is too small - found %u elements, expected %u", + count, expected_count)); + + return (AE_AML_OPERAND_VALUE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_check_package_list + * + * PARAMETERS: data - Pointer to validation data structure + * package - Pointer to package-specific info for method + * elements - Element list of parent package. All elements + * of this list should be of type Package. + * count - Count of subpackages + * + * RETURN: Status + * + * DESCRIPTION: Examine a list of subpackages + * + ******************************************************************************/ + +static acpi_status +acpi_ns_check_package_list(struct acpi_predefined_data *data, + const union acpi_predefined_info *package, + union acpi_operand_object **elements, u32 count) +{ + union acpi_operand_object *sub_package; + union acpi_operand_object **sub_elements; + acpi_status status; + u32 expected_count; + u32 i; + u32 j; + + /* + * Validate each sub-Package in the parent Package + * + * NOTE: assumes list of sub-packages contains no NULL elements. + * Any NULL elements should have been removed by earlier call + * to acpi_ns_remove_null_elements. + */ + for (i = 0; i < count; i++) { + sub_package = *elements; + sub_elements = sub_package->package.elements; + data->parent_package = sub_package; + + /* Each sub-object must be of type Package */ + + status = acpi_ns_check_object_type(data, &sub_package, + ACPI_RTYPE_PACKAGE, i); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* Examine the different types of expected sub-packages */ + + data->parent_package = sub_package; + switch (package->ret_info.type) { + case ACPI_PTYPE2: + case ACPI_PTYPE2_PKG_COUNT: + case ACPI_PTYPE2_REV_FIXED: + + /* Each subpackage has a fixed number of elements */ + + expected_count = + package->ret_info.count1 + package->ret_info.count2; + if (sub_package->package.count < expected_count) { + goto package_too_small; + } + + status = + acpi_ns_check_package_elements(data, sub_elements, + package->ret_info. + object_type1, + package->ret_info. + count1, + package->ret_info. + object_type2, + package->ret_info. + count2, 0); + if (ACPI_FAILURE(status)) { + return (status); + } + break; + + case ACPI_PTYPE2_FIX_VAR: + /* + * Each subpackage has a fixed number of elements and an + * optional element + */ + expected_count = + package->ret_info.count1 + package->ret_info.count2; + if (sub_package->package.count < expected_count) { + goto package_too_small; + } + + status = + acpi_ns_check_package_elements(data, sub_elements, + package->ret_info. + object_type1, + package->ret_info. + count1, + package->ret_info. + object_type2, + sub_package->package. + count - + package->ret_info. + count1, 0); + if (ACPI_FAILURE(status)) { + return (status); + } + break; + + case ACPI_PTYPE2_FIXED: + + /* Each sub-package has a fixed length */ + + expected_count = package->ret_info2.count; + if (sub_package->package.count < expected_count) { + goto package_too_small; + } + + /* Check the type of each sub-package element */ + + for (j = 0; j < expected_count; j++) { + status = + acpi_ns_check_object_type(data, + &sub_elements[j], + package-> + ret_info2. + object_type[j], + j); + if (ACPI_FAILURE(status)) { + return (status); + } + } + break; + + case ACPI_PTYPE2_MIN: + + /* Each sub-package has a variable but minimum length */ + + expected_count = package->ret_info.count1; + if (sub_package->package.count < expected_count) { + goto package_too_small; + } + + /* Check the type of each sub-package element */ + + status = + acpi_ns_check_package_elements(data, sub_elements, + package->ret_info. + object_type1, + sub_package->package. + count, 0, 0, 0); + if (ACPI_FAILURE(status)) { + return (status); + } + break; + + case ACPI_PTYPE2_COUNT: + + /* + * First element is the (Integer) count of elements, including + * the count field (the ACPI name is num_elements) + */ + status = acpi_ns_check_object_type(data, sub_elements, + ACPI_RTYPE_INTEGER, + 0); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* + * Make sure package is large enough for the Count and is + * is as large as the minimum size + */ + expected_count = (u32)(*sub_elements)->integer.value; + if (sub_package->package.count < expected_count) { + goto package_too_small; + } + if (sub_package->package.count < + package->ret_info.count1) { + expected_count = package->ret_info.count1; + goto package_too_small; + } + if (expected_count == 0) { + /* + * Either the num_entries element was originally zero or it was + * a NULL element and repaired to an Integer of value zero. + * In either case, repair it by setting num_entries to be the + * actual size of the subpackage. + */ + expected_count = sub_package->package.count; + (*sub_elements)->integer.value = expected_count; + } + + /* Check the type of each sub-package element */ + + status = + acpi_ns_check_package_elements(data, + (sub_elements + 1), + package->ret_info. + object_type1, + (expected_count - 1), + 0, 0, 1); + if (ACPI_FAILURE(status)) { + return (status); + } + break; + + default: /* Should not get here, type was validated by caller */ + + return (AE_AML_INTERNAL); + } + + elements++; + } + + return (AE_OK); + + package_too_small: + + /* The sub-package count was smaller than required */ + + ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, + "Return Sub-Package[%u] is too small - found %u elements, expected %u", + i, sub_package->package.count, expected_count)); + + return (AE_AML_OPERAND_VALUE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_check_package_elements + * + * PARAMETERS: data - Pointer to validation data structure + * elements - Pointer to the package elements array + * type1 - Object type for first group + * count1 - Count for first group + * type2 - Object type for second group + * count2 - Count for second group + * start_index - Start of the first group of elements + * + * RETURN: Status + * + * DESCRIPTION: Check that all elements of a package are of the correct object + * type. Supports up to two groups of different object types. + * + ******************************************************************************/ + +static acpi_status +acpi_ns_check_package_elements(struct acpi_predefined_data *data, + union acpi_operand_object **elements, + u8 type1, + u32 count1, + u8 type2, u32 count2, u32 start_index) +{ + union acpi_operand_object **this_element = elements; + acpi_status status; + u32 i; + + /* + * Up to two groups of package elements are supported by the data + * structure. All elements in each group must be of the same type. + * The second group can have a count of zero. + */ + for (i = 0; i < count1; i++) { + status = acpi_ns_check_object_type(data, this_element, + type1, i + start_index); + if (ACPI_FAILURE(status)) { + return (status); + } + this_element++; + } + + for (i = 0; i < count2; i++) { + status = acpi_ns_check_object_type(data, this_element, + type2, + (i + count1 + start_index)); + if (ACPI_FAILURE(status)) { + return (status); + } + this_element++; + } + + return (AE_OK); +} diff --git a/drivers/acpi/acpica/nsrepair.c b/drivers/acpi/acpica/nsrepair.c index 8c5f292860fcd02a2cc5936742ac0b6087e026ef..9e833353c06a802bc796b6f102e8f2181a67d2f6 100644 --- a/drivers/acpi/acpica/nsrepair.c +++ b/drivers/acpi/acpica/nsrepair.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nsrepair2.c b/drivers/acpi/acpica/nsrepair2.c index 90189251cdf0e0dce07001b85c84c791621e4c60..ba4d98287c6a14b11add5e457f101876d019d439 100644 --- a/drivers/acpi/acpica/nsrepair2.c +++ b/drivers/acpi/acpica/nsrepair2.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -55,7 +55,8 @@ ACPI_MODULE_NAME("nsrepair2") */ typedef acpi_status(*acpi_repair_function) (struct acpi_predefined_data *data, - union acpi_operand_object **return_object_ptr); + union acpi_operand_object + **return_object_ptr); typedef struct acpi_repair_info { char name[ACPI_NAME_SIZE]; diff --git a/drivers/acpi/acpica/nssearch.c b/drivers/acpi/acpica/nssearch.c index 1d2d8ffc1bc57045e833121c57cb15daa8e797b2..5d43efc53a6179ccd4a50e5997be84306891412c 100644 --- a/drivers/acpi/acpica/nssearch.c +++ b/drivers/acpi/acpica/nssearch.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -328,6 +328,11 @@ acpi_ns_search_and_enter(u32 target_name, if ((status == AE_OK) && (flags & ACPI_NS_ERROR_IF_FOUND)) { status = AE_ALREADY_EXISTS; } +#ifdef ACPI_ASL_COMPILER + if (*return_node && (*return_node)->type == ACPI_TYPE_ANY) { + (*return_node)->flags |= ANOBJ_IS_EXTERNAL; + } +#endif /* Either found it or there was an error: finished either way */ diff --git a/drivers/acpi/acpica/nsutils.c b/drivers/acpi/acpica/nsutils.c index b5b4cb72a8a89bb9bbfca7981d103b178d5f7fcd..686420df684febb610151c937374369da3e65162 100644 --- a/drivers/acpi/acpica/nsutils.c +++ b/drivers/acpi/acpica/nsutils.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -46,14 +46,11 @@ #include "accommon.h" #include "acnamesp.h" #include "amlcode.h" -#include "actables.h" #define _COMPONENT ACPI_NAMESPACE ACPI_MODULE_NAME("nsutils") /* Local prototypes */ -static u8 acpi_ns_valid_path_separator(char sep); - #ifdef ACPI_OBSOLETE_FUNCTIONS acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node *node_to_search); #endif @@ -97,42 +94,6 @@ acpi_ns_print_node_pathname(struct acpi_namespace_node *node, } } -/******************************************************************************* - * - * FUNCTION: acpi_ns_valid_root_prefix - * - * PARAMETERS: prefix - Character to be checked - * - * RETURN: TRUE if a valid prefix - * - * DESCRIPTION: Check if a character is a valid ACPI Root prefix - * - ******************************************************************************/ - -u8 acpi_ns_valid_root_prefix(char prefix) -{ - - return ((u8) (prefix == '\\')); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_valid_path_separator - * - * PARAMETERS: sep - Character to be checked - * - * RETURN: TRUE if a valid path separator - * - * DESCRIPTION: Check if a character is a valid ACPI path separator - * - ******************************************************************************/ - -static u8 acpi_ns_valid_path_separator(char sep) -{ - - return ((u8) (sep == '.')); -} - /******************************************************************************* * * FUNCTION: acpi_ns_get_type @@ -151,10 +112,10 @@ acpi_object_type acpi_ns_get_type(struct acpi_namespace_node * node) if (!node) { ACPI_WARNING((AE_INFO, "Null Node parameter")); - return_UINT32(ACPI_TYPE_ANY); + return_VALUE(ACPI_TYPE_ANY); } - return_UINT32((acpi_object_type) node->type); + return_VALUE(node->type); } /******************************************************************************* @@ -179,10 +140,10 @@ u32 acpi_ns_local(acpi_object_type type) /* Type code out of range */ ACPI_WARNING((AE_INFO, "Invalid Object Type 0x%X", type)); - return_UINT32(ACPI_NS_NORMAL); + return_VALUE(ACPI_NS_NORMAL); } - return_UINT32((u32) acpi_gbl_ns_properties[type] & ACPI_NS_LOCAL); + return_VALUE(acpi_gbl_ns_properties[type] & ACPI_NS_LOCAL); } /******************************************************************************* @@ -218,19 +179,19 @@ void acpi_ns_get_internal_name_length(struct acpi_namestring_info *info) * * strlen() + 1 covers the first name_seg, which has no path separator */ - if (acpi_ns_valid_root_prefix(*next_external_char)) { + if (ACPI_IS_ROOT_PREFIX(*next_external_char)) { info->fully_qualified = TRUE; next_external_char++; /* Skip redundant root_prefix, like \\_SB.PCI0.SBRG.EC0 */ - while (acpi_ns_valid_root_prefix(*next_external_char)) { + while (ACPI_IS_ROOT_PREFIX(*next_external_char)) { next_external_char++; } } else { /* Handle Carat prefixes */ - while (*next_external_char == '^') { + while (ACPI_IS_PARENT_PREFIX(*next_external_char)) { info->num_carats++; next_external_char++; } @@ -244,7 +205,7 @@ void acpi_ns_get_internal_name_length(struct acpi_namestring_info *info) if (*next_external_char) { info->num_segments = 1; for (i = 0; next_external_char[i]; i++) { - if (acpi_ns_valid_path_separator(next_external_char[i])) { + if (ACPI_IS_PATH_SEPARATOR(next_external_char[i])) { info->num_segments++; } } @@ -282,7 +243,7 @@ acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info) /* Setup the correct prefixes, counts, and pointers */ if (info->fully_qualified) { - internal_name[0] = '\\'; + internal_name[0] = AML_ROOT_PREFIX; if (num_segments <= 1) { result = &internal_name[1]; @@ -302,7 +263,7 @@ acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info) i = 0; if (info->num_carats) { for (i = 0; i < info->num_carats; i++) { - internal_name[i] = '^'; + internal_name[i] = AML_PARENT_PREFIX; } } @@ -322,7 +283,7 @@ acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info) for (; num_segments; num_segments--) { for (i = 0; i < ACPI_NAME_SIZE; i++) { - if (acpi_ns_valid_path_separator(*external_name) || + if (ACPI_IS_PATH_SEPARATOR(*external_name) || (*external_name == 0)) { /* Pad the segment with underscore(s) if segment is short */ @@ -339,7 +300,7 @@ acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info) /* Now we must have a path separator, or the pathname is bad */ - if (!acpi_ns_valid_path_separator(*external_name) && + if (!ACPI_IS_PATH_SEPARATOR(*external_name) && (*external_name != 0)) { return_ACPI_STATUS(AE_BAD_PATHNAME); } @@ -457,13 +418,13 @@ acpi_ns_externalize_name(u32 internal_name_length, /* Check for a prefix (one '\' | one or more '^') */ switch (internal_name[0]) { - case '\\': + case AML_ROOT_PREFIX: prefix_length = 1; break; - case '^': + case AML_PARENT_PREFIX: for (i = 0; i < internal_name_length; i++) { - if (internal_name[i] == '^') { + if (ACPI_IS_PARENT_PREFIX(internal_name[i])) { prefix_length = i + 1; } else { break; @@ -664,17 +625,17 @@ void acpi_ns_terminate(void) u32 acpi_ns_opens_scope(acpi_object_type type) { - ACPI_FUNCTION_TRACE_STR(ns_opens_scope, acpi_ut_get_type_name(type)); + ACPI_FUNCTION_ENTRY(); - if (!acpi_ut_valid_object_type(type)) { + if (type > ACPI_TYPE_LOCAL_MAX) { /* type code out of range */ ACPI_WARNING((AE_INFO, "Invalid Object Type 0x%X", type)); - return_UINT32(ACPI_NS_NORMAL); + return (ACPI_NS_NORMAL); } - return_UINT32(((u32) acpi_gbl_ns_properties[type]) & ACPI_NS_NEWSCOPE); + return (((u32)acpi_gbl_ns_properties[type]) & ACPI_NS_NEWSCOPE); } /******************************************************************************* @@ -710,6 +671,8 @@ acpi_ns_get_node(struct acpi_namespace_node *prefix_node, ACPI_FUNCTION_TRACE_PTR(ns_get_node, ACPI_CAST_PTR(char, pathname)); + /* Simplest case is a null pathname */ + if (!pathname) { *return_node = prefix_node; if (!prefix_node) { @@ -718,6 +681,13 @@ acpi_ns_get_node(struct acpi_namespace_node *prefix_node, return_ACPI_STATUS(AE_OK); } + /* Quick check for a reference to the root */ + + if (ACPI_IS_ROOT_PREFIX(pathname[0]) && (!pathname[1])) { + *return_node = acpi_gbl_root_node; + return_ACPI_STATUS(AE_OK); + } + /* Convert path to internal representation */ status = acpi_ns_internalize_name(pathname, &internal_path); diff --git a/drivers/acpi/acpica/nswalk.c b/drivers/acpi/acpica/nswalk.c index 0483877f26b813113cecea55da8e644c902d4eb5..e70911a9e441d3ded8c21cfa4c17a45c00ed936e 100644 --- a/drivers/acpi/acpica/nswalk.c +++ b/drivers/acpi/acpica/nswalk.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -76,12 +76,12 @@ struct acpi_namespace_node *acpi_ns_get_next_node(struct acpi_namespace_node /* It's really the parent's _scope_ that we want */ - return parent_node->child; + return (parent_node->child); } /* Otherwise just return the next peer */ - return child_node->peer; + return (child_node->peer); } /******************************************************************************* diff --git a/drivers/acpi/acpica/nsxfeval.c b/drivers/acpi/acpica/nsxfeval.c index d6a9f77972b6b9f3108e28f757d53562943739d7..fc69949151bb9cc073d61b9702eb6ef1c5fa91fd 100644 --- a/drivers/acpi/acpica/nsxfeval.c +++ b/drivers/acpi/acpica/nsxfeval.c @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -236,7 +236,7 @@ acpi_evaluate_object(acpi_handle handle, * 2) No handle, not fully qualified pathname (error) * 3) Valid handle */ - if ((pathname) && (acpi_ns_valid_root_prefix(pathname[0]))) { + if ((pathname) && (ACPI_IS_ROOT_PREFIX(pathname[0]))) { /* The path is fully qualified, just evaluate by name */ @@ -492,7 +492,7 @@ acpi_walk_namespace(acpi_object_type type, */ status = acpi_ut_acquire_read_lock(&acpi_gbl_namespace_rw_lock); if (ACPI_FAILURE(status)) { - return status; + return_ACPI_STATUS(status); } /* @@ -550,7 +550,7 @@ acpi_ns_get_device_callback(acpi_handle obj_handle, status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + return (status); } node = acpi_ns_validate_handle(obj_handle); @@ -602,17 +602,22 @@ acpi_ns_get_device_callback(acpi_handle obj_handle, /* Walk the CID list */ - found = 0; + found = FALSE; for (i = 0; i < cid->count; i++) { if (ACPI_STRCMP(cid->ids[i].string, info->hid) == 0) { - found = 1; + + /* Found a matching CID */ + + found = TRUE; break; } } + ACPI_FREE(cid); - if (!found) + if (!found) { return (AE_OK); + } } } diff --git a/drivers/acpi/acpica/nsxfname.c b/drivers/acpi/acpica/nsxfname.c index 811c6f13f476c81fbb052da737a2c10fb961de91..f3a4d95899f71ea8578362fa35b5867423028dd2 100644 --- a/drivers/acpi/acpica/nsxfname.c +++ b/drivers/acpi/acpica/nsxfname.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -107,7 +107,7 @@ acpi_get_handle(acpi_handle parent, * * Error for */ - if (acpi_ns_valid_root_prefix(pathname[0])) { + if (ACPI_IS_ROOT_PREFIX(pathname[0])) { /* Pathname is fully qualified (starts with '\') */ @@ -290,7 +290,7 @@ acpi_get_object_info(acpi_handle handle, status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { - goto cleanup; + return (status); } node = acpi_ns_validate_handle(handle); @@ -539,14 +539,14 @@ acpi_status acpi_install_method(u8 *buffer) /* Parameter validation */ if (!buffer) { - return AE_BAD_PARAMETER; + return (AE_BAD_PARAMETER); } /* Table must be a DSDT or SSDT */ if (!ACPI_COMPARE_NAME(table->signature, ACPI_SIG_DSDT) && !ACPI_COMPARE_NAME(table->signature, ACPI_SIG_SSDT)) { - return AE_BAD_HEADER; + return (AE_BAD_HEADER); } /* First AML opcode in the table must be a control method */ @@ -554,7 +554,7 @@ acpi_status acpi_install_method(u8 *buffer) parser_state.aml = buffer + sizeof(struct acpi_table_header); opcode = acpi_ps_peek_opcode(&parser_state); if (opcode != AML_METHOD_OP) { - return AE_BAD_PARAMETER; + return (AE_BAD_PARAMETER); } /* Extract method information from the raw AML */ @@ -572,13 +572,13 @@ acpi_status acpi_install_method(u8 *buffer) */ aml_buffer = ACPI_ALLOCATE(aml_length); if (!aml_buffer) { - return AE_NO_MEMORY; + return (AE_NO_MEMORY); } method_obj = acpi_ut_create_internal_object(ACPI_TYPE_METHOD); if (!method_obj) { ACPI_FREE(aml_buffer); - return AE_NO_MEMORY; + return (AE_NO_MEMORY); } /* Lock namespace for acpi_ns_lookup, we may be creating a new node */ @@ -644,12 +644,12 @@ acpi_status acpi_install_method(u8 *buffer) /* Remove local reference to the method object */ acpi_ut_remove_reference(method_obj); - return status; + return (status); error_exit: ACPI_FREE(aml_buffer); ACPI_FREE(method_obj); - return status; + return (status); } ACPI_EXPORT_SYMBOL(acpi_install_method) diff --git a/drivers/acpi/acpica/nsxfobj.c b/drivers/acpi/acpica/nsxfobj.c index 9d029dac6b64382e0164f5b63b7a9312b101d31e..c0853ef294e4749832f429c962de6a2a59348676 100644 --- a/drivers/acpi/acpica/nsxfobj.c +++ b/drivers/acpi/acpica/nsxfobj.c @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/psargs.c b/drivers/acpi/acpica/psargs.c index cb79e2d4d7430a6d524ff10151c3efcd2b65ea2a..f51308cdbc65527c11a382545831d214103d03b4 100644 --- a/drivers/acpi/acpica/psargs.c +++ b/drivers/acpi/acpica/psargs.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -108,7 +108,7 @@ acpi_ps_get_next_package_length(struct acpi_parse_state *parser_state) /* Byte 0 is a special case, either bits [0:3] or [0:5] are used */ package_length |= (aml[0] & byte_zero_mask); - return_UINT32(package_length); + return_VALUE(package_length); } /******************************************************************************* @@ -162,7 +162,7 @@ char *acpi_ps_get_next_namestring(struct acpi_parse_state *parser_state) /* Point past any namestring prefix characters (backslash or carat) */ - while (acpi_ps_is_prefix_char(*end)) { + while (ACPI_IS_ROOT_PREFIX(*end) || ACPI_IS_PARENT_PREFIX(*end)) { end++; } @@ -798,7 +798,8 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state, subop = acpi_ps_peek_opcode(parser_state); if (subop == 0 || acpi_ps_is_leading_char(subop) || - acpi_ps_is_prefix_char(subop)) { + ACPI_IS_ROOT_PREFIX(subop) || + ACPI_IS_PARENT_PREFIX(subop)) { /* null_name or name_string */ diff --git a/drivers/acpi/acpica/psloop.c b/drivers/acpi/acpica/psloop.c index 5607805aab26b0907ae6014fa363bed179350d34..63c4554474817b591fdc0d71771dde8f2cf970ed 100644 --- a/drivers/acpi/acpica/psloop.c +++ b/drivers/acpi/acpica/psloop.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -58,350 +58,15 @@ #define _COMPONENT ACPI_PARSER ACPI_MODULE_NAME("psloop") -static u32 acpi_gbl_depth = 0; - /* Local prototypes */ - -static acpi_status acpi_ps_get_aml_opcode(struct acpi_walk_state *walk_state); - -static acpi_status -acpi_ps_build_named_op(struct acpi_walk_state *walk_state, - u8 * aml_op_start, - union acpi_parse_object *unnamed_op, - union acpi_parse_object **op); - -static acpi_status -acpi_ps_create_op(struct acpi_walk_state *walk_state, - u8 * aml_op_start, union acpi_parse_object **new_op); - static acpi_status acpi_ps_get_arguments(struct acpi_walk_state *walk_state, u8 * aml_op_start, union acpi_parse_object *op); -static acpi_status -acpi_ps_complete_op(struct acpi_walk_state *walk_state, - union acpi_parse_object **op, acpi_status status); - -static acpi_status -acpi_ps_complete_final_op(struct acpi_walk_state *walk_state, - union acpi_parse_object *op, acpi_status status); - static void acpi_ps_link_module_code(union acpi_parse_object *parent_op, u8 *aml_start, u32 aml_length, acpi_owner_id owner_id); -/******************************************************************************* - * - * FUNCTION: acpi_ps_get_aml_opcode - * - * PARAMETERS: walk_state - Current state - * - * RETURN: Status - * - * DESCRIPTION: Extract the next AML opcode from the input stream. - * - ******************************************************************************/ - -static acpi_status acpi_ps_get_aml_opcode(struct acpi_walk_state *walk_state) -{ - - ACPI_FUNCTION_TRACE_PTR(ps_get_aml_opcode, walk_state); - - walk_state->aml_offset = - (u32) ACPI_PTR_DIFF(walk_state->parser_state.aml, - walk_state->parser_state.aml_start); - walk_state->opcode = acpi_ps_peek_opcode(&(walk_state->parser_state)); - - /* - * First cut to determine what we have found: - * 1) A valid AML opcode - * 2) A name string - * 3) An unknown/invalid opcode - */ - walk_state->op_info = acpi_ps_get_opcode_info(walk_state->opcode); - - switch (walk_state->op_info->class) { - case AML_CLASS_ASCII: - case AML_CLASS_PREFIX: - /* - * Starts with a valid prefix or ASCII char, this is a name - * string. Convert the bare name string to a namepath. - */ - walk_state->opcode = AML_INT_NAMEPATH_OP; - walk_state->arg_types = ARGP_NAMESTRING; - break; - - case AML_CLASS_UNKNOWN: - - /* The opcode is unrecognized. Complain and skip unknown opcodes */ - - if (walk_state->pass_number == 2) { - ACPI_ERROR((AE_INFO, - "Unknown opcode 0x%.2X at table offset 0x%.4X, ignoring", - walk_state->opcode, - (u32)(walk_state->aml_offset + - sizeof(struct acpi_table_header)))); - - ACPI_DUMP_BUFFER(walk_state->parser_state.aml - 16, 48); - -#ifdef ACPI_ASL_COMPILER - /* - * This is executed for the disassembler only. Output goes - * to the disassembled ASL output file. - */ - acpi_os_printf - ("/*\nError: Unknown opcode 0x%.2X at table offset 0x%.4X, context:\n", - walk_state->opcode, - (u32)(walk_state->aml_offset + - sizeof(struct acpi_table_header))); - - /* Dump the context surrounding the invalid opcode */ - - acpi_ut_dump_buffer(((u8 *)walk_state->parser_state. - aml - 16), 48, DB_BYTE_DISPLAY, - walk_state->aml_offset + - sizeof(struct acpi_table_header) - - 16); - acpi_os_printf(" */\n"); -#endif - } - - /* Increment past one-byte or two-byte opcode */ - - walk_state->parser_state.aml++; - if (walk_state->opcode > 0xFF) { /* Can only happen if first byte is 0x5B */ - walk_state->parser_state.aml++; - } - - return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE); - - default: - - /* Found opcode info, this is a normal opcode */ - - walk_state->parser_state.aml += - acpi_ps_get_opcode_size(walk_state->opcode); - walk_state->arg_types = walk_state->op_info->parse_args; - break; - } - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_build_named_op - * - * PARAMETERS: walk_state - Current state - * aml_op_start - Begin of named Op in AML - * unnamed_op - Early Op (not a named Op) - * op - Returned Op - * - * RETURN: Status - * - * DESCRIPTION: Parse a named Op - * - ******************************************************************************/ - -static acpi_status -acpi_ps_build_named_op(struct acpi_walk_state *walk_state, - u8 * aml_op_start, - union acpi_parse_object *unnamed_op, - union acpi_parse_object **op) -{ - acpi_status status = AE_OK; - union acpi_parse_object *arg = NULL; - - ACPI_FUNCTION_TRACE_PTR(ps_build_named_op, walk_state); - - unnamed_op->common.value.arg = NULL; - unnamed_op->common.arg_list_length = 0; - unnamed_op->common.aml_opcode = walk_state->opcode; - - /* - * Get and append arguments until we find the node that contains - * the name (the type ARGP_NAME). - */ - while (GET_CURRENT_ARG_TYPE(walk_state->arg_types) && - (GET_CURRENT_ARG_TYPE(walk_state->arg_types) != ARGP_NAME)) { - status = - acpi_ps_get_next_arg(walk_state, - &(walk_state->parser_state), - GET_CURRENT_ARG_TYPE(walk_state-> - arg_types), &arg); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - acpi_ps_append_arg(unnamed_op, arg); - INCREMENT_ARG_LIST(walk_state->arg_types); - } - - /* - * Make sure that we found a NAME and didn't run out of arguments - */ - if (!GET_CURRENT_ARG_TYPE(walk_state->arg_types)) { - return_ACPI_STATUS(AE_AML_NO_OPERAND); - } - - /* We know that this arg is a name, move to next arg */ - - INCREMENT_ARG_LIST(walk_state->arg_types); - - /* - * Find the object. This will either insert the object into - * the namespace or simply look it up - */ - walk_state->op = NULL; - - status = walk_state->descending_callback(walk_state, op); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "During name lookup/catalog")); - return_ACPI_STATUS(status); - } - - if (!*op) { - return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE); - } - - status = acpi_ps_next_parse_state(walk_state, *op, status); - if (ACPI_FAILURE(status)) { - if (status == AE_CTRL_PENDING) { - return_ACPI_STATUS(AE_CTRL_PARSE_PENDING); - } - return_ACPI_STATUS(status); - } - - acpi_ps_append_arg(*op, unnamed_op->common.value.arg); - acpi_gbl_depth++; - - if ((*op)->common.aml_opcode == AML_REGION_OP || - (*op)->common.aml_opcode == AML_DATA_REGION_OP) { - /* - * Defer final parsing of an operation_region body, because we don't - * have enough info in the first pass to parse it correctly (i.e., - * there may be method calls within the term_arg elements of the body.) - * - * However, we must continue parsing because the opregion is not a - * standalone package -- we don't know where the end is at this point. - * - * (Length is unknown until parse of the body complete) - */ - (*op)->named.data = aml_op_start; - (*op)->named.length = 0; - } - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_create_op - * - * PARAMETERS: walk_state - Current state - * aml_op_start - Op start in AML - * new_op - Returned Op - * - * RETURN: Status - * - * DESCRIPTION: Get Op from AML - * - ******************************************************************************/ - -static acpi_status -acpi_ps_create_op(struct acpi_walk_state *walk_state, - u8 * aml_op_start, union acpi_parse_object **new_op) -{ - acpi_status status = AE_OK; - union acpi_parse_object *op; - union acpi_parse_object *named_op = NULL; - union acpi_parse_object *parent_scope; - u8 argument_count; - const struct acpi_opcode_info *op_info; - - ACPI_FUNCTION_TRACE_PTR(ps_create_op, walk_state); - - status = acpi_ps_get_aml_opcode(walk_state); - if (status == AE_CTRL_PARSE_CONTINUE) { - return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE); - } - - /* Create Op structure and append to parent's argument list */ - - walk_state->op_info = acpi_ps_get_opcode_info(walk_state->opcode); - op = acpi_ps_alloc_op(walk_state->opcode); - if (!op) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - if (walk_state->op_info->flags & AML_NAMED) { - status = - acpi_ps_build_named_op(walk_state, aml_op_start, op, - &named_op); - acpi_ps_free_op(op); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - *new_op = named_op; - return_ACPI_STATUS(AE_OK); - } - - /* Not a named opcode, just allocate Op and append to parent */ - - if (walk_state->op_info->flags & AML_CREATE) { - /* - * Backup to beginning of create_XXXfield declaration - * body_length is unknown until we parse the body - */ - op->named.data = aml_op_start; - op->named.length = 0; - } - - if (walk_state->opcode == AML_BANK_FIELD_OP) { - /* - * Backup to beginning of bank_field declaration - * body_length is unknown until we parse the body - */ - op->named.data = aml_op_start; - op->named.length = 0; - } - - parent_scope = acpi_ps_get_parent_scope(&(walk_state->parser_state)); - acpi_ps_append_arg(parent_scope, op); - - if (parent_scope) { - op_info = - acpi_ps_get_opcode_info(parent_scope->common.aml_opcode); - if (op_info->flags & AML_HAS_TARGET) { - argument_count = - acpi_ps_get_argument_count(op_info->type); - if (parent_scope->common.arg_list_length > - argument_count) { - op->common.flags |= ACPI_PARSEOP_TARGET; - } - } else if (parent_scope->common.aml_opcode == AML_INCREMENT_OP) { - op->common.flags |= ACPI_PARSEOP_TARGET; - } - } - - if (walk_state->descending_callback != NULL) { - /* - * Find the object. This will either insert the object into - * the namespace or simply look it up - */ - walk_state->op = *new_op = op; - - status = walk_state->descending_callback(walk_state, &op); - status = acpi_ps_next_parse_state(walk_state, op, status); - if (status == AE_CTRL_PENDING) { - status = AE_CTRL_PARSE_PENDING; - } - } - - return_ACPI_STATUS(status); -} - /******************************************************************************* * * FUNCTION: acpi_ps_get_arguments @@ -709,288 +374,6 @@ acpi_ps_link_module_code(union acpi_parse_object *parent_op, } } -/******************************************************************************* - * - * FUNCTION: acpi_ps_complete_op - * - * PARAMETERS: walk_state - Current state - * op - Returned Op - * status - Parse status before complete Op - * - * RETURN: Status - * - * DESCRIPTION: Complete Op - * - ******************************************************************************/ - -static acpi_status -acpi_ps_complete_op(struct acpi_walk_state *walk_state, - union acpi_parse_object **op, acpi_status status) -{ - acpi_status status2; - - ACPI_FUNCTION_TRACE_PTR(ps_complete_op, walk_state); - - /* - * Finished one argument of the containing scope - */ - walk_state->parser_state.scope->parse_scope.arg_count--; - - /* Close this Op (will result in parse subtree deletion) */ - - status2 = acpi_ps_complete_this_op(walk_state, *op); - if (ACPI_FAILURE(status2)) { - return_ACPI_STATUS(status2); - } - - *op = NULL; - - switch (status) { - case AE_OK: - break; - - case AE_CTRL_TRANSFER: - - /* We are about to transfer to a called method */ - - walk_state->prev_op = NULL; - walk_state->prev_arg_types = walk_state->arg_types; - return_ACPI_STATUS(status); - - case AE_CTRL_END: - - acpi_ps_pop_scope(&(walk_state->parser_state), op, - &walk_state->arg_types, - &walk_state->arg_count); - - if (*op) { - walk_state->op = *op; - walk_state->op_info = - acpi_ps_get_opcode_info((*op)->common.aml_opcode); - walk_state->opcode = (*op)->common.aml_opcode; - - status = walk_state->ascending_callback(walk_state); - status = - acpi_ps_next_parse_state(walk_state, *op, status); - - status2 = acpi_ps_complete_this_op(walk_state, *op); - if (ACPI_FAILURE(status2)) { - return_ACPI_STATUS(status2); - } - } - - status = AE_OK; - break; - - case AE_CTRL_BREAK: - case AE_CTRL_CONTINUE: - - /* Pop off scopes until we find the While */ - - while (!(*op) || ((*op)->common.aml_opcode != AML_WHILE_OP)) { - acpi_ps_pop_scope(&(walk_state->parser_state), op, - &walk_state->arg_types, - &walk_state->arg_count); - } - - /* Close this iteration of the While loop */ - - walk_state->op = *op; - walk_state->op_info = - acpi_ps_get_opcode_info((*op)->common.aml_opcode); - walk_state->opcode = (*op)->common.aml_opcode; - - status = walk_state->ascending_callback(walk_state); - status = acpi_ps_next_parse_state(walk_state, *op, status); - - status2 = acpi_ps_complete_this_op(walk_state, *op); - if (ACPI_FAILURE(status2)) { - return_ACPI_STATUS(status2); - } - - status = AE_OK; - break; - - case AE_CTRL_TERMINATE: - - /* Clean up */ - do { - if (*op) { - status2 = - acpi_ps_complete_this_op(walk_state, *op); - if (ACPI_FAILURE(status2)) { - return_ACPI_STATUS(status2); - } - - acpi_ut_delete_generic_state - (acpi_ut_pop_generic_state - (&walk_state->control_state)); - } - - acpi_ps_pop_scope(&(walk_state->parser_state), op, - &walk_state->arg_types, - &walk_state->arg_count); - - } while (*op); - - return_ACPI_STATUS(AE_OK); - - default: /* All other non-AE_OK status */ - - do { - if (*op) { - status2 = - acpi_ps_complete_this_op(walk_state, *op); - if (ACPI_FAILURE(status2)) { - return_ACPI_STATUS(status2); - } - } - - acpi_ps_pop_scope(&(walk_state->parser_state), op, - &walk_state->arg_types, - &walk_state->arg_count); - - } while (*op); - -#if 0 - /* - * TBD: Cleanup parse ops on error - */ - if (*op == NULL) { - acpi_ps_pop_scope(parser_state, op, - &walk_state->arg_types, - &walk_state->arg_count); - } -#endif - walk_state->prev_op = NULL; - walk_state->prev_arg_types = walk_state->arg_types; - return_ACPI_STATUS(status); - } - - /* This scope complete? */ - - if (acpi_ps_has_completed_scope(&(walk_state->parser_state))) { - acpi_ps_pop_scope(&(walk_state->parser_state), op, - &walk_state->arg_types, - &walk_state->arg_count); - ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Popped scope, Op=%p\n", *op)); - } else { - *op = NULL; - } - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_complete_final_op - * - * PARAMETERS: walk_state - Current state - * op - Current Op - * status - Current parse status before complete last - * Op - * - * RETURN: Status - * - * DESCRIPTION: Complete last Op. - * - ******************************************************************************/ - -static acpi_status -acpi_ps_complete_final_op(struct acpi_walk_state *walk_state, - union acpi_parse_object *op, acpi_status status) -{ - acpi_status status2; - - ACPI_FUNCTION_TRACE_PTR(ps_complete_final_op, walk_state); - - /* - * Complete the last Op (if not completed), and clear the scope stack. - * It is easily possible to end an AML "package" with an unbounded number - * of open scopes (such as when several ASL blocks are closed with - * sequential closing braces). We want to terminate each one cleanly. - */ - ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "AML package complete at Op %p\n", - op)); - do { - if (op) { - if (walk_state->ascending_callback != NULL) { - walk_state->op = op; - walk_state->op_info = - acpi_ps_get_opcode_info(op->common. - aml_opcode); - walk_state->opcode = op->common.aml_opcode; - - status = - walk_state->ascending_callback(walk_state); - status = - acpi_ps_next_parse_state(walk_state, op, - status); - if (status == AE_CTRL_PENDING) { - status = - acpi_ps_complete_op(walk_state, &op, - AE_OK); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - - if (status == AE_CTRL_TERMINATE) { - status = AE_OK; - - /* Clean up */ - do { - if (op) { - status2 = - acpi_ps_complete_this_op - (walk_state, op); - if (ACPI_FAILURE - (status2)) { - return_ACPI_STATUS - (status2); - } - } - - acpi_ps_pop_scope(& - (walk_state-> - parser_state), - &op, - &walk_state-> - arg_types, - &walk_state-> - arg_count); - - } while (op); - - return_ACPI_STATUS(status); - } - - else if (ACPI_FAILURE(status)) { - - /* First error is most important */ - - (void) - acpi_ps_complete_this_op(walk_state, - op); - return_ACPI_STATUS(status); - } - } - - status2 = acpi_ps_complete_this_op(walk_state, op); - if (ACPI_FAILURE(status2)) { - return_ACPI_STATUS(status2); - } - } - - acpi_ps_pop_scope(&(walk_state->parser_state), &op, - &walk_state->arg_types, - &walk_state->arg_count); - - } while (op); - - return_ACPI_STATUS(status); -} - /******************************************************************************* * * FUNCTION: acpi_ps_parse_loop @@ -1177,10 +560,6 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) walk_state->op_info = acpi_ps_get_opcode_info(op->common.aml_opcode); if (walk_state->op_info->flags & AML_NAMED) { - if (acpi_gbl_depth) { - acpi_gbl_depth--; - } - if (op->common.aml_opcode == AML_REGION_OP || op->common.aml_opcode == AML_DATA_REGION_OP) { /* diff --git a/drivers/acpi/acpica/psobject.c b/drivers/acpi/acpica/psobject.c new file mode 100644 index 0000000000000000000000000000000000000000..12c4028002b145e0fef8b9ed60ab9f00ccd100dc --- /dev/null +++ b/drivers/acpi/acpica/psobject.c @@ -0,0 +1,647 @@ +/****************************************************************************** + * + * Module Name: psobject - Support for parse objects + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2013, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include "accommon.h" +#include "acparser.h" +#include "amlcode.h" + +#define _COMPONENT ACPI_PARSER +ACPI_MODULE_NAME("psobject") + +/* Local prototypes */ +static acpi_status acpi_ps_get_aml_opcode(struct acpi_walk_state *walk_state); + +/******************************************************************************* + * + * FUNCTION: acpi_ps_get_aml_opcode + * + * PARAMETERS: walk_state - Current state + * + * RETURN: Status + * + * DESCRIPTION: Extract the next AML opcode from the input stream. + * + ******************************************************************************/ + +static acpi_status acpi_ps_get_aml_opcode(struct acpi_walk_state *walk_state) +{ + + ACPI_FUNCTION_TRACE_PTR(ps_get_aml_opcode, walk_state); + + walk_state->aml_offset = + (u32)ACPI_PTR_DIFF(walk_state->parser_state.aml, + walk_state->parser_state.aml_start); + walk_state->opcode = acpi_ps_peek_opcode(&(walk_state->parser_state)); + + /* + * First cut to determine what we have found: + * 1) A valid AML opcode + * 2) A name string + * 3) An unknown/invalid opcode + */ + walk_state->op_info = acpi_ps_get_opcode_info(walk_state->opcode); + + switch (walk_state->op_info->class) { + case AML_CLASS_ASCII: + case AML_CLASS_PREFIX: + /* + * Starts with a valid prefix or ASCII char, this is a name + * string. Convert the bare name string to a namepath. + */ + walk_state->opcode = AML_INT_NAMEPATH_OP; + walk_state->arg_types = ARGP_NAMESTRING; + break; + + case AML_CLASS_UNKNOWN: + + /* The opcode is unrecognized. Complain and skip unknown opcodes */ + + if (walk_state->pass_number == 2) { + ACPI_ERROR((AE_INFO, + "Unknown opcode 0x%.2X at table offset 0x%.4X, ignoring", + walk_state->opcode, + (u32)(walk_state->aml_offset + + sizeof(struct acpi_table_header)))); + + ACPI_DUMP_BUFFER((walk_state->parser_state.aml - 16), + 48); + +#ifdef ACPI_ASL_COMPILER + /* + * This is executed for the disassembler only. Output goes + * to the disassembled ASL output file. + */ + acpi_os_printf + ("/*\nError: Unknown opcode 0x%.2X at table offset 0x%.4X, context:\n", + walk_state->opcode, + (u32)(walk_state->aml_offset + + sizeof(struct acpi_table_header))); + + /* Dump the context surrounding the invalid opcode */ + + acpi_ut_dump_buffer(((u8 *)walk_state->parser_state. + aml - 16), 48, DB_BYTE_DISPLAY, + (walk_state->aml_offset + + sizeof(struct acpi_table_header) - + 16)); + acpi_os_printf(" */\n"); +#endif + } + + /* Increment past one-byte or two-byte opcode */ + + walk_state->parser_state.aml++; + if (walk_state->opcode > 0xFF) { /* Can only happen if first byte is 0x5B */ + walk_state->parser_state.aml++; + } + + return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE); + + default: + + /* Found opcode info, this is a normal opcode */ + + walk_state->parser_state.aml += + acpi_ps_get_opcode_size(walk_state->opcode); + walk_state->arg_types = walk_state->op_info->parse_args; + break; + } + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_build_named_op + * + * PARAMETERS: walk_state - Current state + * aml_op_start - Begin of named Op in AML + * unnamed_op - Early Op (not a named Op) + * op - Returned Op + * + * RETURN: Status + * + * DESCRIPTION: Parse a named Op + * + ******************************************************************************/ + +acpi_status +acpi_ps_build_named_op(struct acpi_walk_state *walk_state, + u8 *aml_op_start, + union acpi_parse_object *unnamed_op, + union acpi_parse_object **op) +{ + acpi_status status = AE_OK; + union acpi_parse_object *arg = NULL; + + ACPI_FUNCTION_TRACE_PTR(ps_build_named_op, walk_state); + + unnamed_op->common.value.arg = NULL; + unnamed_op->common.arg_list_length = 0; + unnamed_op->common.aml_opcode = walk_state->opcode; + + /* + * Get and append arguments until we find the node that contains + * the name (the type ARGP_NAME). + */ + while (GET_CURRENT_ARG_TYPE(walk_state->arg_types) && + (GET_CURRENT_ARG_TYPE(walk_state->arg_types) != ARGP_NAME)) { + status = + acpi_ps_get_next_arg(walk_state, + &(walk_state->parser_state), + GET_CURRENT_ARG_TYPE(walk_state-> + arg_types), &arg); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + acpi_ps_append_arg(unnamed_op, arg); + INCREMENT_ARG_LIST(walk_state->arg_types); + } + + /* + * Make sure that we found a NAME and didn't run out of arguments + */ + if (!GET_CURRENT_ARG_TYPE(walk_state->arg_types)) { + return_ACPI_STATUS(AE_AML_NO_OPERAND); + } + + /* We know that this arg is a name, move to next arg */ + + INCREMENT_ARG_LIST(walk_state->arg_types); + + /* + * Find the object. This will either insert the object into + * the namespace or simply look it up + */ + walk_state->op = NULL; + + status = walk_state->descending_callback(walk_state, op); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, "During name lookup/catalog")); + return_ACPI_STATUS(status); + } + + if (!*op) { + return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE); + } + + status = acpi_ps_next_parse_state(walk_state, *op, status); + if (ACPI_FAILURE(status)) { + if (status == AE_CTRL_PENDING) { + return_ACPI_STATUS(AE_CTRL_PARSE_PENDING); + } + return_ACPI_STATUS(status); + } + + acpi_ps_append_arg(*op, unnamed_op->common.value.arg); + + if ((*op)->common.aml_opcode == AML_REGION_OP || + (*op)->common.aml_opcode == AML_DATA_REGION_OP) { + /* + * Defer final parsing of an operation_region body, because we don't + * have enough info in the first pass to parse it correctly (i.e., + * there may be method calls within the term_arg elements of the body.) + * + * However, we must continue parsing because the opregion is not a + * standalone package -- we don't know where the end is at this point. + * + * (Length is unknown until parse of the body complete) + */ + (*op)->named.data = aml_op_start; + (*op)->named.length = 0; + } + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_create_op + * + * PARAMETERS: walk_state - Current state + * aml_op_start - Op start in AML + * new_op - Returned Op + * + * RETURN: Status + * + * DESCRIPTION: Get Op from AML + * + ******************************************************************************/ + +acpi_status +acpi_ps_create_op(struct acpi_walk_state *walk_state, + u8 *aml_op_start, union acpi_parse_object **new_op) +{ + acpi_status status = AE_OK; + union acpi_parse_object *op; + union acpi_parse_object *named_op = NULL; + union acpi_parse_object *parent_scope; + u8 argument_count; + const struct acpi_opcode_info *op_info; + + ACPI_FUNCTION_TRACE_PTR(ps_create_op, walk_state); + + status = acpi_ps_get_aml_opcode(walk_state); + if (status == AE_CTRL_PARSE_CONTINUE) { + return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE); + } + + /* Create Op structure and append to parent's argument list */ + + walk_state->op_info = acpi_ps_get_opcode_info(walk_state->opcode); + op = acpi_ps_alloc_op(walk_state->opcode); + if (!op) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + if (walk_state->op_info->flags & AML_NAMED) { + status = + acpi_ps_build_named_op(walk_state, aml_op_start, op, + &named_op); + acpi_ps_free_op(op); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + *new_op = named_op; + return_ACPI_STATUS(AE_OK); + } + + /* Not a named opcode, just allocate Op and append to parent */ + + if (walk_state->op_info->flags & AML_CREATE) { + /* + * Backup to beginning of create_XXXfield declaration + * body_length is unknown until we parse the body + */ + op->named.data = aml_op_start; + op->named.length = 0; + } + + if (walk_state->opcode == AML_BANK_FIELD_OP) { + /* + * Backup to beginning of bank_field declaration + * body_length is unknown until we parse the body + */ + op->named.data = aml_op_start; + op->named.length = 0; + } + + parent_scope = acpi_ps_get_parent_scope(&(walk_state->parser_state)); + acpi_ps_append_arg(parent_scope, op); + + if (parent_scope) { + op_info = + acpi_ps_get_opcode_info(parent_scope->common.aml_opcode); + if (op_info->flags & AML_HAS_TARGET) { + argument_count = + acpi_ps_get_argument_count(op_info->type); + if (parent_scope->common.arg_list_length > + argument_count) { + op->common.flags |= ACPI_PARSEOP_TARGET; + } + } else if (parent_scope->common.aml_opcode == AML_INCREMENT_OP) { + op->common.flags |= ACPI_PARSEOP_TARGET; + } + } + + if (walk_state->descending_callback != NULL) { + /* + * Find the object. This will either insert the object into + * the namespace or simply look it up + */ + walk_state->op = *new_op = op; + + status = walk_state->descending_callback(walk_state, &op); + status = acpi_ps_next_parse_state(walk_state, op, status); + if (status == AE_CTRL_PENDING) { + status = AE_CTRL_PARSE_PENDING; + } + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_complete_op + * + * PARAMETERS: walk_state - Current state + * op - Returned Op + * status - Parse status before complete Op + * + * RETURN: Status + * + * DESCRIPTION: Complete Op + * + ******************************************************************************/ + +acpi_status +acpi_ps_complete_op(struct acpi_walk_state *walk_state, + union acpi_parse_object **op, acpi_status status) +{ + acpi_status status2; + + ACPI_FUNCTION_TRACE_PTR(ps_complete_op, walk_state); + + /* + * Finished one argument of the containing scope + */ + walk_state->parser_state.scope->parse_scope.arg_count--; + + /* Close this Op (will result in parse subtree deletion) */ + + status2 = acpi_ps_complete_this_op(walk_state, *op); + if (ACPI_FAILURE(status2)) { + return_ACPI_STATUS(status2); + } + + *op = NULL; + + switch (status) { + case AE_OK: + break; + + case AE_CTRL_TRANSFER: + + /* We are about to transfer to a called method */ + + walk_state->prev_op = NULL; + walk_state->prev_arg_types = walk_state->arg_types; + return_ACPI_STATUS(status); + + case AE_CTRL_END: + + acpi_ps_pop_scope(&(walk_state->parser_state), op, + &walk_state->arg_types, + &walk_state->arg_count); + + if (*op) { + walk_state->op = *op; + walk_state->op_info = + acpi_ps_get_opcode_info((*op)->common.aml_opcode); + walk_state->opcode = (*op)->common.aml_opcode; + + status = walk_state->ascending_callback(walk_state); + status = + acpi_ps_next_parse_state(walk_state, *op, status); + + status2 = acpi_ps_complete_this_op(walk_state, *op); + if (ACPI_FAILURE(status2)) { + return_ACPI_STATUS(status2); + } + } + + status = AE_OK; + break; + + case AE_CTRL_BREAK: + case AE_CTRL_CONTINUE: + + /* Pop off scopes until we find the While */ + + while (!(*op) || ((*op)->common.aml_opcode != AML_WHILE_OP)) { + acpi_ps_pop_scope(&(walk_state->parser_state), op, + &walk_state->arg_types, + &walk_state->arg_count); + } + + /* Close this iteration of the While loop */ + + walk_state->op = *op; + walk_state->op_info = + acpi_ps_get_opcode_info((*op)->common.aml_opcode); + walk_state->opcode = (*op)->common.aml_opcode; + + status = walk_state->ascending_callback(walk_state); + status = acpi_ps_next_parse_state(walk_state, *op, status); + + status2 = acpi_ps_complete_this_op(walk_state, *op); + if (ACPI_FAILURE(status2)) { + return_ACPI_STATUS(status2); + } + + status = AE_OK; + break; + + case AE_CTRL_TERMINATE: + + /* Clean up */ + do { + if (*op) { + status2 = + acpi_ps_complete_this_op(walk_state, *op); + if (ACPI_FAILURE(status2)) { + return_ACPI_STATUS(status2); + } + + acpi_ut_delete_generic_state + (acpi_ut_pop_generic_state + (&walk_state->control_state)); + } + + acpi_ps_pop_scope(&(walk_state->parser_state), op, + &walk_state->arg_types, + &walk_state->arg_count); + + } while (*op); + + return_ACPI_STATUS(AE_OK); + + default: /* All other non-AE_OK status */ + + do { + if (*op) { + status2 = + acpi_ps_complete_this_op(walk_state, *op); + if (ACPI_FAILURE(status2)) { + return_ACPI_STATUS(status2); + } + } + + acpi_ps_pop_scope(&(walk_state->parser_state), op, + &walk_state->arg_types, + &walk_state->arg_count); + + } while (*op); + +#if 0 + /* + * TBD: Cleanup parse ops on error + */ + if (*op == NULL) { + acpi_ps_pop_scope(parser_state, op, + &walk_state->arg_types, + &walk_state->arg_count); + } +#endif + walk_state->prev_op = NULL; + walk_state->prev_arg_types = walk_state->arg_types; + return_ACPI_STATUS(status); + } + + /* This scope complete? */ + + if (acpi_ps_has_completed_scope(&(walk_state->parser_state))) { + acpi_ps_pop_scope(&(walk_state->parser_state), op, + &walk_state->arg_types, + &walk_state->arg_count); + ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Popped scope, Op=%p\n", *op)); + } else { + *op = NULL; + } + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_complete_final_op + * + * PARAMETERS: walk_state - Current state + * op - Current Op + * status - Current parse status before complete last + * Op + * + * RETURN: Status + * + * DESCRIPTION: Complete last Op. + * + ******************************************************************************/ + +acpi_status +acpi_ps_complete_final_op(struct acpi_walk_state *walk_state, + union acpi_parse_object *op, acpi_status status) +{ + acpi_status status2; + + ACPI_FUNCTION_TRACE_PTR(ps_complete_final_op, walk_state); + + /* + * Complete the last Op (if not completed), and clear the scope stack. + * It is easily possible to end an AML "package" with an unbounded number + * of open scopes (such as when several ASL blocks are closed with + * sequential closing braces). We want to terminate each one cleanly. + */ + ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "AML package complete at Op %p\n", + op)); + do { + if (op) { + if (walk_state->ascending_callback != NULL) { + walk_state->op = op; + walk_state->op_info = + acpi_ps_get_opcode_info(op->common. + aml_opcode); + walk_state->opcode = op->common.aml_opcode; + + status = + walk_state->ascending_callback(walk_state); + status = + acpi_ps_next_parse_state(walk_state, op, + status); + if (status == AE_CTRL_PENDING) { + status = + acpi_ps_complete_op(walk_state, &op, + AE_OK); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + + if (status == AE_CTRL_TERMINATE) { + status = AE_OK; + + /* Clean up */ + do { + if (op) { + status2 = + acpi_ps_complete_this_op + (walk_state, op); + if (ACPI_FAILURE + (status2)) { + return_ACPI_STATUS + (status2); + } + } + + acpi_ps_pop_scope(& + (walk_state-> + parser_state), + &op, + &walk_state-> + arg_types, + &walk_state-> + arg_count); + + } while (op); + + return_ACPI_STATUS(status); + } + + else if (ACPI_FAILURE(status)) { + + /* First error is most important */ + + (void) + acpi_ps_complete_this_op(walk_state, + op); + return_ACPI_STATUS(status); + } + } + + status2 = acpi_ps_complete_this_op(walk_state, op); + if (ACPI_FAILURE(status2)) { + return_ACPI_STATUS(status2); + } + } + + acpi_ps_pop_scope(&(walk_state->parser_state), &op, + &walk_state->arg_types, + &walk_state->arg_count); + + } while (op); + + return_ACPI_STATUS(status); +} diff --git a/drivers/acpi/acpica/psopcode.c b/drivers/acpi/acpica/psopcode.c index 1793d934aa30b1b918154d4bf3e73af64b64d8e8..1b659e59710ab525d85cbd6674c900b3da746f36 100644 --- a/drivers/acpi/acpica/psopcode.c +++ b/drivers/acpi/acpica/psopcode.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -43,16 +43,12 @@ #include #include "accommon.h" -#include "acparser.h" #include "acopcode.h" #include "amlcode.h" #define _COMPONENT ACPI_PARSER ACPI_MODULE_NAME("psopcode") -static const u8 acpi_gbl_argument_count[] = - { 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 6 }; - /******************************************************************************* * * NAME: acpi_gbl_aml_op_info @@ -63,7 +59,6 @@ static const u8 acpi_gbl_argument_count[] = * the operand type. * ******************************************************************************/ - /* * Summary of opcode types/flags * @@ -181,7 +176,6 @@ static const u8 acpi_gbl_argument_count[] = AML_CREATE_QWORD_FIELD_OP ******************************************************************************/ - /* * Master Opcode information table. A summary of everything we know about each * opcode, all in one place. @@ -656,169 +650,3 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = { /*! [End] no source code translation !*/ }; - -/* - * This table is directly indexed by the opcodes, and returns an - * index into the table above - */ -static const u8 acpi_gbl_short_op_index[256] = { -/* 0 1 2 3 4 5 6 7 */ -/* 8 9 A B C D E F */ -/* 0x00 */ 0x00, 0x01, _UNK, _UNK, _UNK, _UNK, 0x02, _UNK, -/* 0x08 */ 0x03, _UNK, 0x04, 0x05, 0x06, 0x07, 0x6E, _UNK, -/* 0x10 */ 0x08, 0x09, 0x0a, 0x6F, 0x0b, _UNK, _UNK, _UNK, -/* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x20 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x28 */ _UNK, _UNK, _UNK, _UNK, _UNK, 0x63, _PFX, _PFX, -/* 0x30 */ 0x67, 0x66, 0x68, 0x65, 0x69, 0x64, 0x6A, 0x7D, -/* 0x38 */ 0x7F, 0x80, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x40 */ _UNK, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, -/* 0x48 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, -/* 0x50 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, -/* 0x58 */ _ASC, _ASC, _ASC, _UNK, _PFX, _UNK, _PFX, _ASC, -/* 0x60 */ 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, -/* 0x68 */ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, _UNK, -/* 0x70 */ 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, -/* 0x78 */ 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, -/* 0x80 */ 0x2b, 0x2c, 0x2d, 0x2e, 0x70, 0x71, 0x2f, 0x30, -/* 0x88 */ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x72, -/* 0x90 */ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x73, 0x74, -/* 0x98 */ 0x75, 0x76, _UNK, _UNK, 0x77, 0x78, 0x79, 0x7A, -/* 0xA0 */ 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x60, 0x61, -/* 0xA8 */ 0x62, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0xB0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0xB8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0xC0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0xC8 */ _UNK, _UNK, _UNK, _UNK, 0x44, _UNK, _UNK, _UNK, -/* 0xD0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0xD8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0xE0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0xE8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0xF0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0xF8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x45, -}; - -/* - * This table is indexed by the second opcode of the extended opcode - * pair. It returns an index into the opcode table (acpi_gbl_aml_op_info) - */ -static const u8 acpi_gbl_long_op_index[NUM_EXTENDED_OPCODE] = { -/* 0 1 2 3 4 5 6 7 */ -/* 8 9 A B C D E F */ -/* 0x00 */ _UNK, 0x46, 0x47, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x08 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x10 */ _UNK, _UNK, 0x48, 0x49, _UNK, _UNK, _UNK, _UNK, -/* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x7B, -/* 0x20 */ 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, -/* 0x28 */ 0x52, 0x53, 0x54, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x30 */ 0x55, 0x56, 0x57, 0x7e, _UNK, _UNK, _UNK, _UNK, -/* 0x38 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x40 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x48 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x50 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x58 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x60 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x68 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x70 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x78 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x80 */ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, -/* 0x88 */ 0x7C, -}; - -/******************************************************************************* - * - * FUNCTION: acpi_ps_get_opcode_info - * - * PARAMETERS: opcode - The AML opcode - * - * RETURN: A pointer to the info about the opcode. - * - * DESCRIPTION: Find AML opcode description based on the opcode. - * NOTE: This procedure must ALWAYS return a valid pointer! - * - ******************************************************************************/ - -const struct acpi_opcode_info *acpi_ps_get_opcode_info(u16 opcode) -{ - ACPI_FUNCTION_NAME(ps_get_opcode_info); - - /* - * Detect normal 8-bit opcode or extended 16-bit opcode - */ - if (!(opcode & 0xFF00)) { - - /* Simple (8-bit) opcode: 0-255, can't index beyond table */ - - return (&acpi_gbl_aml_op_info - [acpi_gbl_short_op_index[(u8) opcode]]); - } - - if (((opcode & 0xFF00) == AML_EXTENDED_OPCODE) && - (((u8) opcode) <= MAX_EXTENDED_OPCODE)) { - - /* Valid extended (16-bit) opcode */ - - return (&acpi_gbl_aml_op_info - [acpi_gbl_long_op_index[(u8) opcode]]); - } - - /* Unknown AML opcode */ - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Unknown AML opcode [%4.4X]\n", opcode)); - - return (&acpi_gbl_aml_op_info[_UNK]); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_get_opcode_name - * - * PARAMETERS: opcode - The AML opcode - * - * RETURN: A pointer to the name of the opcode (ASCII String) - * Note: Never returns NULL. - * - * DESCRIPTION: Translate an opcode into a human-readable string - * - ******************************************************************************/ - -char *acpi_ps_get_opcode_name(u16 opcode) -{ -#if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUG_OUTPUT) - - const struct acpi_opcode_info *op; - - op = acpi_ps_get_opcode_info(opcode); - - /* Always guaranteed to return a valid pointer */ - - return (op->name); - -#else - return ("OpcodeName unavailable"); - -#endif -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_get_argument_count - * - * PARAMETERS: op_type - Type associated with the AML opcode - * - * RETURN: Argument count - * - * DESCRIPTION: Obtain the number of expected arguments for an AML opcode - * - ******************************************************************************/ - -u8 acpi_ps_get_argument_count(u32 op_type) -{ - - if (op_type <= AML_TYPE_EXEC_6A_0T_1R) { - return (acpi_gbl_argument_count[op_type]); - } - - return (0); -} diff --git a/drivers/acpi/acpica/psopinfo.c b/drivers/acpi/acpica/psopinfo.c new file mode 100644 index 0000000000000000000000000000000000000000..9ba5301e57516ea83450809f29c38e9cd2a09421 --- /dev/null +++ b/drivers/acpi/acpica/psopinfo.c @@ -0,0 +1,223 @@ +/****************************************************************************** + * + * Module Name: psopinfo - AML opcode information functions and dispatch tables + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2013, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include "accommon.h" +#include "acparser.h" +#include "acopcode.h" +#include "amlcode.h" + +#define _COMPONENT ACPI_PARSER +ACPI_MODULE_NAME("psopinfo") + +extern const u8 acpi_gbl_short_op_index[]; +extern const u8 acpi_gbl_long_op_index[]; + +static const u8 acpi_gbl_argument_count[] = + { 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 6 }; + +/******************************************************************************* + * + * FUNCTION: acpi_ps_get_opcode_info + * + * PARAMETERS: opcode - The AML opcode + * + * RETURN: A pointer to the info about the opcode. + * + * DESCRIPTION: Find AML opcode description based on the opcode. + * NOTE: This procedure must ALWAYS return a valid pointer! + * + ******************************************************************************/ + +const struct acpi_opcode_info *acpi_ps_get_opcode_info(u16 opcode) +{ + ACPI_FUNCTION_NAME(ps_get_opcode_info); + + /* + * Detect normal 8-bit opcode or extended 16-bit opcode + */ + if (!(opcode & 0xFF00)) { + + /* Simple (8-bit) opcode: 0-255, can't index beyond table */ + + return (&acpi_gbl_aml_op_info + [acpi_gbl_short_op_index[(u8)opcode]]); + } + + if (((opcode & 0xFF00) == AML_EXTENDED_OPCODE) && + (((u8)opcode) <= MAX_EXTENDED_OPCODE)) { + + /* Valid extended (16-bit) opcode */ + + return (&acpi_gbl_aml_op_info + [acpi_gbl_long_op_index[(u8)opcode]]); + } + + /* Unknown AML opcode */ + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Unknown AML opcode [%4.4X]\n", opcode)); + + return (&acpi_gbl_aml_op_info[_UNK]); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_get_opcode_name + * + * PARAMETERS: opcode - The AML opcode + * + * RETURN: A pointer to the name of the opcode (ASCII String) + * Note: Never returns NULL. + * + * DESCRIPTION: Translate an opcode into a human-readable string + * + ******************************************************************************/ + +char *acpi_ps_get_opcode_name(u16 opcode) +{ +#if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUG_OUTPUT) + + const struct acpi_opcode_info *op; + + op = acpi_ps_get_opcode_info(opcode); + + /* Always guaranteed to return a valid pointer */ + + return (op->name); + +#else + return ("OpcodeName unavailable"); + +#endif +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_get_argument_count + * + * PARAMETERS: op_type - Type associated with the AML opcode + * + * RETURN: Argument count + * + * DESCRIPTION: Obtain the number of expected arguments for an AML opcode + * + ******************************************************************************/ + +u8 acpi_ps_get_argument_count(u32 op_type) +{ + + if (op_type <= AML_TYPE_EXEC_6A_0T_1R) { + return (acpi_gbl_argument_count[op_type]); + } + + return (0); +} + +/* + * This table is directly indexed by the opcodes It returns + * an index into the opcode table (acpi_gbl_aml_op_info) + */ +const u8 acpi_gbl_short_op_index[256] = { +/* 0 1 2 3 4 5 6 7 */ +/* 8 9 A B C D E F */ +/* 0x00 */ 0x00, 0x01, _UNK, _UNK, _UNK, _UNK, 0x02, _UNK, +/* 0x08 */ 0x03, _UNK, 0x04, 0x05, 0x06, 0x07, 0x6E, _UNK, +/* 0x10 */ 0x08, 0x09, 0x0a, 0x6F, 0x0b, _UNK, _UNK, _UNK, +/* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x20 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x28 */ _UNK, _UNK, _UNK, _UNK, _UNK, 0x63, _PFX, _PFX, +/* 0x30 */ 0x67, 0x66, 0x68, 0x65, 0x69, 0x64, 0x6A, 0x7D, +/* 0x38 */ 0x7F, 0x80, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x40 */ _UNK, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, +/* 0x48 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, +/* 0x50 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, +/* 0x58 */ _ASC, _ASC, _ASC, _UNK, _PFX, _UNK, _PFX, _ASC, +/* 0x60 */ 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, +/* 0x68 */ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, _UNK, +/* 0x70 */ 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, +/* 0x78 */ 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, +/* 0x80 */ 0x2b, 0x2c, 0x2d, 0x2e, 0x70, 0x71, 0x2f, 0x30, +/* 0x88 */ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x72, +/* 0x90 */ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x73, 0x74, +/* 0x98 */ 0x75, 0x76, _UNK, _UNK, 0x77, 0x78, 0x79, 0x7A, +/* 0xA0 */ 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x60, 0x61, +/* 0xA8 */ 0x62, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xB0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xB8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xC0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xC8 */ _UNK, _UNK, _UNK, _UNK, 0x44, _UNK, _UNK, _UNK, +/* 0xD0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xD8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xE0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xE8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xF0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xF8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x45, +}; + +/* + * This table is indexed by the second opcode of the extended opcode + * pair. It returns an index into the opcode table (acpi_gbl_aml_op_info) + */ +const u8 acpi_gbl_long_op_index[NUM_EXTENDED_OPCODE] = { +/* 0 1 2 3 4 5 6 7 */ +/* 8 9 A B C D E F */ +/* 0x00 */ _UNK, 0x46, 0x47, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x08 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x10 */ _UNK, _UNK, 0x48, 0x49, _UNK, _UNK, _UNK, _UNK, +/* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x7B, +/* 0x20 */ 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, +/* 0x28 */ 0x52, 0x53, 0x54, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x30 */ 0x55, 0x56, 0x57, 0x7e, _UNK, _UNK, _UNK, _UNK, +/* 0x38 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x40 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x48 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x50 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x58 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x60 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x68 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x70 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x78 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x80 */ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, +/* 0x88 */ 0x7C, +}; diff --git a/drivers/acpi/acpica/psparse.c b/drivers/acpi/acpica/psparse.c index 2494caf4775541e1de60b4b3c1fcfa95cc7b4dda..abc4c48b2eddd7c18acb854a5eeb960d73080393 100644 --- a/drivers/acpi/acpica/psparse.c +++ b/drivers/acpi/acpica/psparse.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/psscope.c b/drivers/acpi/acpica/psscope.c index 608dc20dc173b93845dba6025ccaf14d5d745ef7..6a4b6fb39f32e197767a46aeef54711ad9df2bfc 100644 --- a/drivers/acpi/acpica/psscope.c +++ b/drivers/acpi/acpica/psscope.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/pstree.c b/drivers/acpi/acpica/pstree.c index fdb2e71f30461153036a117a7424036af1049b75..c1934bf04f0af56f16db267dcdc5d3a914b749ab 100644 --- a/drivers/acpi/acpica/pstree.c +++ b/drivers/acpi/acpica/pstree.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/psutils.c b/drivers/acpi/acpica/psutils.c index 4137dcb352d14e3d26989a111b8f18c07381f877..91fa73a6e55e7245ff9147b769a0a32f3c509864 100644 --- a/drivers/acpi/acpica/psutils.c +++ b/drivers/acpi/acpica/psutils.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -201,14 +201,6 @@ u8 acpi_ps_is_leading_char(u32 c) return ((u8) (c == '_' || (c >= 'A' && c <= 'Z'))); } -/* - * Is "c" a namestring prefix character? - */ -u8 acpi_ps_is_prefix_char(u32 c) -{ - return ((u8) (c == '\\' || c == '^')); -} - /* * Get op's name (4-byte name segment) or 0 if unnamed */ diff --git a/drivers/acpi/acpica/pswalk.c b/drivers/acpi/acpica/pswalk.c index ab96cf47896d33e9a28b7854306c5011dbfff970..abd65624754f20175721dea4e570e7fa0a2d887c 100644 --- a/drivers/acpi/acpica/pswalk.c +++ b/drivers/acpi/acpica/pswalk.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/psxface.c b/drivers/acpi/acpica/psxface.c index 963e1622579779c19d201e00c90e10188ddf9210..f682542689656d5ce98ba93db973fad907d41899 100644 --- a/drivers/acpi/acpica/psxface.c +++ b/drivers/acpi/acpica/psxface.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/rsaddr.c b/drivers/acpi/acpica/rsaddr.c index 856ff075b6ab9a523b740f150bccba6561ee31ea..f3a9276ac665035adefb27e949fa842a6a629802 100644 --- a/drivers/acpi/acpica/rsaddr.c +++ b/drivers/acpi/acpica/rsaddr.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/rscalc.c b/drivers/acpi/acpica/rscalc.c index 147feb6aa2a0b3bdf26a9887ca84c362a2532cdc..7816d4eef04e1afebf0a0b8aea0b660a4f81b62f 100644 --- a/drivers/acpi/acpica/rscalc.c +++ b/drivers/acpi/acpica/rscalc.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -84,7 +84,7 @@ static u8 acpi_rs_count_set_bits(u16 bit_field) bit_field &= (u16) (bit_field - 1); } - return bits_set; + return (bits_set); } /******************************************************************************* @@ -407,7 +407,9 @@ acpi_rs_get_list_length(u8 * aml_buffer, /* Validate the Resource Type and Resource Length */ - status = acpi_ut_validate_resource(aml_buffer, &resource_index); + status = + acpi_ut_validate_resource(NULL, aml_buffer, + &resource_index); if (ACPI_FAILURE(status)) { /* * Exit on failure. Cannot continue because the descriptor length diff --git a/drivers/acpi/acpica/rscreate.c b/drivers/acpi/acpica/rscreate.c index 311cbc4f05fa18350e0b45c7b866a9b50503358a..f8b55b426c9d9b83abfe7f1d1a42692406cf0cc7 100644 --- a/drivers/acpi/acpica/rscreate.c +++ b/drivers/acpi/acpica/rscreate.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -98,7 +98,7 @@ acpi_buffer_to_resource(u8 *aml_buffer, /* Perform the AML-to-Resource conversion */ - status = acpi_ut_walk_aml_resources(aml_buffer, aml_buffer_length, + status = acpi_ut_walk_aml_resources(NULL, aml_buffer, aml_buffer_length, acpi_rs_convert_aml_to_resources, ¤t_resource_ptr); if (status == AE_AML_NO_RESOURCE_END_TAG) { @@ -174,7 +174,7 @@ acpi_rs_create_resource_list(union acpi_operand_object *aml_buffer, /* Do the conversion */ resource = output_buffer->pointer; - status = acpi_ut_walk_aml_resources(aml_start, aml_buffer_length, + status = acpi_ut_walk_aml_resources(NULL, aml_start, aml_buffer_length, acpi_rs_convert_aml_to_resources, &resource); if (ACPI_FAILURE(status)) { @@ -480,8 +480,7 @@ acpi_rs_create_aml_resources(struct acpi_resource *linked_list_buffer, status = acpi_rs_get_aml_length(linked_list_buffer, &aml_size_needed); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "AmlSizeNeeded=%X, %s\n", - (u32) aml_size_needed, - acpi_format_exception(status))); + (u32)aml_size_needed, acpi_format_exception(status))); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/rsdump.c b/drivers/acpi/acpica/rsdump.c index 4d11b072388c910915ee063f711fccd99f04561a..cab51445189d03b649f27ebf5000be33634bdb61 100644 --- a/drivers/acpi/acpica/rsdump.c +++ b/drivers/acpi/acpica/rsdump.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -77,419 +77,16 @@ static void acpi_rs_dump_address_common(union acpi_resource_data *resource); static void acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table); -#define ACPI_RSD_OFFSET(f) (u8) ACPI_OFFSET (union acpi_resource_data,f) -#define ACPI_PRT_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_pci_routing_table,f) -#define ACPI_RSD_TABLE_SIZE(name) (sizeof(name) / sizeof (struct acpi_rsdump_info)) - -/******************************************************************************* - * - * Resource Descriptor info tables - * - * Note: The first table entry must be a Title or Literal and must contain - * the table length (number of table entries) - * - ******************************************************************************/ - -struct acpi_rsdump_info acpi_rs_dump_irq[7] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_irq), "IRQ", NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(irq.descriptor_length), - "Descriptor Length", NULL}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.triggering), "Triggering", - acpi_gbl_he_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.polarity), "Polarity", - acpi_gbl_ll_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.sharable), "Sharing", - acpi_gbl_shr_decode}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(irq.interrupt_count), - "Interrupt Count", NULL}, - {ACPI_RSD_SHORTLIST, ACPI_RSD_OFFSET(irq.interrupts[0]), - "Interrupt List", NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_dma[6] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_dma), "DMA", NULL}, - {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(dma.type), "Speed", - acpi_gbl_typ_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(dma.bus_master), "Mastering", - acpi_gbl_bm_decode}, - {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(dma.transfer), "Transfer Type", - acpi_gbl_siz_decode}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(dma.channel_count), "Channel Count", - NULL}, - {ACPI_RSD_SHORTLIST, ACPI_RSD_OFFSET(dma.channels[0]), "Channel List", - NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_start_dpf[4] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_start_dpf), - "Start-Dependent-Functions", NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(start_dpf.descriptor_length), - "Descriptor Length", NULL}, - {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(start_dpf.compatibility_priority), - "Compatibility Priority", acpi_gbl_config_decode}, - {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(start_dpf.performance_robustness), - "Performance/Robustness", acpi_gbl_config_decode} -}; - -struct acpi_rsdump_info acpi_rs_dump_end_dpf[1] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_end_dpf), - "End-Dependent-Functions", NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_io[6] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_io), "I/O", NULL}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(io.io_decode), "Address Decoding", - acpi_gbl_io_decode}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(io.minimum), "Address Minimum", NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(io.maximum), "Address Maximum", NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(io.alignment), "Alignment", NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(io.address_length), "Address Length", - NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_fixed_io[3] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_fixed_io), - "Fixed I/O", NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(fixed_io.address), "Address", NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(fixed_io.address_length), - "Address Length", NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_vendor[3] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_vendor), - "Vendor Specific", NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(vendor.byte_length), "Length", NULL}, - {ACPI_RSD_LONGLIST, ACPI_RSD_OFFSET(vendor.byte_data[0]), "Vendor Data", - NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_end_tag[1] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_end_tag), "EndTag", - NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_memory24[6] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_memory24), - "24-Bit Memory Range", NULL}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(memory24.write_protect), - "Write Protect", acpi_gbl_rw_decode}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.minimum), "Address Minimum", - NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.maximum), "Address Maximum", - NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.alignment), "Alignment", - NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.address_length), - "Address Length", NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_memory32[6] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_memory32), - "32-Bit Memory Range", NULL}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(memory32.write_protect), - "Write Protect", acpi_gbl_rw_decode}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.minimum), "Address Minimum", - NULL}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.maximum), "Address Maximum", - NULL}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.alignment), "Alignment", - NULL}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.address_length), - "Address Length", NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_fixed_memory32[4] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_fixed_memory32), - "32-Bit Fixed Memory Range", NULL}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(fixed_memory32.write_protect), - "Write Protect", acpi_gbl_rw_decode}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(fixed_memory32.address), "Address", - NULL}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(fixed_memory32.address_length), - "Address Length", NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_address16[8] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_address16), - "16-Bit WORD Address Space", NULL}, - {ACPI_RSD_ADDRESS, 0, NULL, NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.granularity), "Granularity", - NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.minimum), "Address Minimum", - NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.maximum), "Address Maximum", - NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.translation_offset), - "Translation Offset", NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.address_length), - "Address Length", NULL}, - {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(address16.resource_source), NULL, NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_address32[8] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_address32), - "32-Bit DWORD Address Space", NULL}, - {ACPI_RSD_ADDRESS, 0, NULL, NULL}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.granularity), "Granularity", - NULL}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.minimum), "Address Minimum", - NULL}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.maximum), "Address Maximum", - NULL}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.translation_offset), - "Translation Offset", NULL}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.address_length), - "Address Length", NULL}, - {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(address32.resource_source), NULL, NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_address64[8] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_address64), - "64-Bit QWORD Address Space", NULL}, - {ACPI_RSD_ADDRESS, 0, NULL, NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.granularity), "Granularity", - NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.minimum), "Address Minimum", - NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.maximum), "Address Maximum", - NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.translation_offset), - "Translation Offset", NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.address_length), - "Address Length", NULL}, - {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(address64.resource_source), NULL, NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_ext_address64[8] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_ext_address64), - "64-Bit Extended Address Space", NULL}, - {ACPI_RSD_ADDRESS, 0, NULL, NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.granularity), - "Granularity", NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.minimum), - "Address Minimum", NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.maximum), - "Address Maximum", NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.translation_offset), - "Translation Offset", NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.address_length), - "Address Length", NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.type_specific), - "Type-Specific Attribute", NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_ext_irq[8] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_ext_irq), - "Extended IRQ", NULL}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.producer_consumer), - "Type", acpi_gbl_consume_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.triggering), - "Triggering", acpi_gbl_he_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.polarity), "Polarity", - acpi_gbl_ll_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.sharable), "Sharing", - acpi_gbl_shr_decode}, - {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(extended_irq.resource_source), NULL, - NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(extended_irq.interrupt_count), - "Interrupt Count", NULL}, - {ACPI_RSD_DWORDLIST, ACPI_RSD_OFFSET(extended_irq.interrupts[0]), - "Interrupt List", NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_generic_reg[6] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_generic_reg), - "Generic Register", NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(generic_reg.space_id), "Space ID", - NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(generic_reg.bit_width), "Bit Width", - NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(generic_reg.bit_offset), "Bit Offset", - NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(generic_reg.access_size), - "Access Size", NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(generic_reg.address), "Address", NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_gpio[16] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_gpio), "GPIO", NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(gpio.revision_id), "RevisionId", NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(gpio.connection_type), - "ConnectionType", acpi_gbl_ct_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(gpio.producer_consumer), - "ProducerConsumer", acpi_gbl_consume_decode}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(gpio.pin_config), "PinConfig", - acpi_gbl_ppc_decode}, - {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(gpio.sharable), "Sharable", - acpi_gbl_shr_decode}, - {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(gpio.io_restriction), - "IoRestriction", acpi_gbl_ior_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(gpio.triggering), "Triggering", - acpi_gbl_he_decode}, - {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(gpio.polarity), "Polarity", - acpi_gbl_ll_decode}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(gpio.drive_strength), "DriveStrength", - NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(gpio.debounce_timeout), - "DebounceTimeout", NULL}, - {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(gpio.resource_source), - "ResourceSource", NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(gpio.pin_table_length), - "PinTableLength", NULL}, - {ACPI_RSD_WORDLIST, ACPI_RSD_OFFSET(gpio.pin_table), "PinTable", NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(gpio.vendor_length), "VendorLength", - NULL}, - {ACPI_RSD_SHORTLISTX, ACPI_RSD_OFFSET(gpio.vendor_data), "VendorData", - NULL}, -}; - -struct acpi_rsdump_info acpi_rs_dump_fixed_dma[4] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_fixed_dma), - "FixedDma", NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(fixed_dma.request_lines), - "RequestLines", NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(fixed_dma.channels), "Channels", - NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(fixed_dma.width), "TransferWidth", - acpi_gbl_dts_decode}, -}; - -#define ACPI_RS_DUMP_COMMON_SERIAL_BUS \ - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (common_serial_bus.revision_id), "RevisionId", NULL}, \ - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (common_serial_bus.type), "Type", acpi_gbl_sbt_decode}, \ - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (common_serial_bus.producer_consumer), "ProducerConsumer", acpi_gbl_consume_decode}, \ - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (common_serial_bus.slave_mode), "SlaveMode", acpi_gbl_sm_decode}, \ - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (common_serial_bus.type_revision_id), "TypeRevisionId", NULL}, \ - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (common_serial_bus.type_data_length), "TypeDataLength", NULL}, \ - {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET (common_serial_bus.resource_source), "ResourceSource", NULL}, \ - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (common_serial_bus.vendor_length), "VendorLength", NULL}, \ - {ACPI_RSD_SHORTLISTX,ACPI_RSD_OFFSET (common_serial_bus.vendor_data), "VendorData", NULL}, - -struct acpi_rsdump_info acpi_rs_dump_common_serial_bus[10] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_common_serial_bus), - "Common Serial Bus", NULL}, - ACPI_RS_DUMP_COMMON_SERIAL_BUS -}; - -struct acpi_rsdump_info acpi_rs_dump_i2c_serial_bus[13] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_i2c_serial_bus), - "I2C Serial Bus", NULL}, - ACPI_RS_DUMP_COMMON_SERIAL_BUS {ACPI_RSD_1BITFLAG, - ACPI_RSD_OFFSET(i2c_serial_bus. - access_mode), - "AccessMode", acpi_gbl_am_decode}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(i2c_serial_bus.connection_speed), - "ConnectionSpeed", NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(i2c_serial_bus.slave_address), - "SlaveAddress", NULL}, -}; - -struct acpi_rsdump_info acpi_rs_dump_spi_serial_bus[17] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_spi_serial_bus), - "Spi Serial Bus", NULL}, - ACPI_RS_DUMP_COMMON_SERIAL_BUS {ACPI_RSD_1BITFLAG, - ACPI_RSD_OFFSET(spi_serial_bus. - wire_mode), "WireMode", - acpi_gbl_wm_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(spi_serial_bus.device_polarity), - "DevicePolarity", acpi_gbl_dp_decode}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(spi_serial_bus.data_bit_length), - "DataBitLength", NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(spi_serial_bus.clock_phase), - "ClockPhase", acpi_gbl_cph_decode}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(spi_serial_bus.clock_polarity), - "ClockPolarity", acpi_gbl_cpo_decode}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(spi_serial_bus.device_selection), - "DeviceSelection", NULL}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(spi_serial_bus.connection_speed), - "ConnectionSpeed", NULL}, -}; - -struct acpi_rsdump_info acpi_rs_dump_uart_serial_bus[19] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_uart_serial_bus), - "Uart Serial Bus", NULL}, - ACPI_RS_DUMP_COMMON_SERIAL_BUS {ACPI_RSD_2BITFLAG, - ACPI_RSD_OFFSET(uart_serial_bus. - flow_control), - "FlowControl", acpi_gbl_fc_decode}, - {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(uart_serial_bus.stop_bits), - "StopBits", acpi_gbl_sb_decode}, - {ACPI_RSD_3BITFLAG, ACPI_RSD_OFFSET(uart_serial_bus.data_bits), - "DataBits", acpi_gbl_bpb_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(uart_serial_bus.endian), "Endian", - acpi_gbl_ed_decode}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(uart_serial_bus.parity), "Parity", - acpi_gbl_pt_decode}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(uart_serial_bus.lines_enabled), - "LinesEnabled", NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(uart_serial_bus.rx_fifo_size), - "RxFifoSize", NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(uart_serial_bus.tx_fifo_size), - "TxFifoSize", NULL}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(uart_serial_bus.default_baud_rate), - "ConnectionSpeed", NULL}, -}; - -/* - * Tables used for common address descriptor flag fields - */ -static struct acpi_rsdump_info acpi_rs_dump_general_flags[5] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_general_flags), NULL, - NULL}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.producer_consumer), - "Consumer/Producer", acpi_gbl_consume_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.decode), "Address Decode", - acpi_gbl_dec_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.min_address_fixed), - "Min Relocatability", acpi_gbl_min_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.max_address_fixed), - "Max Relocatability", acpi_gbl_max_decode} -}; - -static struct acpi_rsdump_info acpi_rs_dump_memory_flags[5] = { - {ACPI_RSD_LITERAL, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_memory_flags), - "Resource Type", (void *)"Memory Range"}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.mem.write_protect), - "Write Protect", acpi_gbl_rw_decode}, - {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(address.info.mem.caching), - "Caching", acpi_gbl_mem_decode}, - {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(address.info.mem.range_type), - "Range Type", acpi_gbl_mtp_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.mem.translation), - "Translation", acpi_gbl_ttp_decode} -}; - -static struct acpi_rsdump_info acpi_rs_dump_io_flags[4] = { - {ACPI_RSD_LITERAL, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_io_flags), - "Resource Type", (void *)"I/O Range"}, - {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(address.info.io.range_type), - "Range Type", acpi_gbl_rng_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.io.translation), - "Translation", acpi_gbl_ttp_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.io.translation_type), - "Translation Type", acpi_gbl_trs_decode} -}; - -/* - * Table used to dump _PRT contents - */ -static struct acpi_rsdump_info acpi_rs_dump_prt[5] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_prt), NULL, NULL}, - {ACPI_RSD_UINT64, ACPI_PRT_OFFSET(address), "Address", NULL}, - {ACPI_RSD_UINT32, ACPI_PRT_OFFSET(pin), "Pin", NULL}, - {ACPI_RSD_STRING, ACPI_PRT_OFFSET(source[0]), "Source", NULL}, - {ACPI_RSD_UINT32, ACPI_PRT_OFFSET(source_index), "Source Index", NULL} -}; - /******************************************************************************* * * FUNCTION: acpi_rs_dump_descriptor * - * PARAMETERS: Resource + * PARAMETERS: resource - Buffer containing the resource + * table - Table entry to decode the resource * * RETURN: None * - * DESCRIPTION: + * DESCRIPTION: Dump a resource descriptor based on a dump table entry. * ******************************************************************************/ @@ -654,7 +251,8 @@ acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table) /* * Optional resource_source for Address resources */ - acpi_rs_dump_resource_source(ACPI_CAST_PTR(struct + acpi_rs_dump_resource_source(ACPI_CAST_PTR + (struct acpi_resource_source, target)); break; @@ -765,8 +363,9 @@ void acpi_rs_dump_resource_list(struct acpi_resource *resource_list) ACPI_FUNCTION_ENTRY(); - if (!(acpi_dbg_level & ACPI_LV_RESOURCES) - || !(_COMPONENT & acpi_dbg_layer)) { + /* Check if debug output enabled */ + + if (!ACPI_IS_DEBUG_ENABLED(ACPI_LV_RESOURCES, _COMPONENT)) { return; } @@ -827,8 +426,9 @@ void acpi_rs_dump_irq_list(u8 * route_table) ACPI_FUNCTION_ENTRY(); - if (!(acpi_dbg_level & ACPI_LV_RESOURCES) - || !(_COMPONENT & acpi_dbg_layer)) { + /* Check if debug output enabled */ + + if (!ACPI_IS_DEBUG_ENABLED(ACPI_LV_RESOURCES, _COMPONENT)) { return; } diff --git a/drivers/acpi/acpica/rsdumpinfo.c b/drivers/acpi/acpica/rsdumpinfo.c new file mode 100644 index 0000000000000000000000000000000000000000..46192bd5365335e97120269519c097fd6c2aa7be --- /dev/null +++ b/drivers/acpi/acpica/rsdumpinfo.c @@ -0,0 +1,454 @@ +/******************************************************************************* + * + * Module Name: rsdumpinfo - Tables used to display resource descriptors. + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2013, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include "accommon.h" +#include "acresrc.h" + +#define _COMPONENT ACPI_RESOURCES +ACPI_MODULE_NAME("rsdumpinfo") + +#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) +#define ACPI_RSD_OFFSET(f) (u8) ACPI_OFFSET (union acpi_resource_data,f) +#define ACPI_PRT_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_pci_routing_table,f) +#define ACPI_RSD_TABLE_SIZE(name) (sizeof(name) / sizeof (struct acpi_rsdump_info)) +/******************************************************************************* + * + * Resource Descriptor info tables + * + * Note: The first table entry must be a Title or Literal and must contain + * the table length (number of table entries) + * + ******************************************************************************/ +struct acpi_rsdump_info acpi_rs_dump_irq[7] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_irq), "IRQ", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(irq.descriptor_length), + "Descriptor Length", NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.triggering), "Triggering", + acpi_gbl_he_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.polarity), "Polarity", + acpi_gbl_ll_decode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(irq.sharable), "Sharing", + acpi_gbl_shr_decode}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(irq.interrupt_count), + "Interrupt Count", NULL}, + {ACPI_RSD_SHORTLIST, ACPI_RSD_OFFSET(irq.interrupts[0]), + "Interrupt List", NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_dma[6] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_dma), "DMA", NULL}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(dma.type), "Speed", + acpi_gbl_typ_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(dma.bus_master), "Mastering", + acpi_gbl_bm_decode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(dma.transfer), "Transfer Type", + acpi_gbl_siz_decode}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(dma.channel_count), "Channel Count", + NULL}, + {ACPI_RSD_SHORTLIST, ACPI_RSD_OFFSET(dma.channels[0]), "Channel List", + NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_start_dpf[4] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_start_dpf), + "Start-Dependent-Functions", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(start_dpf.descriptor_length), + "Descriptor Length", NULL}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(start_dpf.compatibility_priority), + "Compatibility Priority", acpi_gbl_config_decode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(start_dpf.performance_robustness), + "Performance/Robustness", acpi_gbl_config_decode} +}; + +struct acpi_rsdump_info acpi_rs_dump_end_dpf[1] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_end_dpf), + "End-Dependent-Functions", NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_io[6] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_io), "I/O", NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(io.io_decode), "Address Decoding", + acpi_gbl_io_decode}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(io.minimum), "Address Minimum", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(io.maximum), "Address Maximum", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(io.alignment), "Alignment", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(io.address_length), "Address Length", + NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_fixed_io[3] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_fixed_io), + "Fixed I/O", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(fixed_io.address), "Address", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(fixed_io.address_length), + "Address Length", NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_vendor[3] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_vendor), + "Vendor Specific", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(vendor.byte_length), "Length", NULL}, + {ACPI_RSD_LONGLIST, ACPI_RSD_OFFSET(vendor.byte_data[0]), "Vendor Data", + NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_end_tag[1] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_end_tag), "EndTag", + NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_memory24[6] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_memory24), + "24-Bit Memory Range", NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(memory24.write_protect), + "Write Protect", acpi_gbl_rw_decode}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.minimum), "Address Minimum", + NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.maximum), "Address Maximum", + NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.alignment), "Alignment", + NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.address_length), + "Address Length", NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_memory32[6] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_memory32), + "32-Bit Memory Range", NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(memory32.write_protect), + "Write Protect", acpi_gbl_rw_decode}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.minimum), "Address Minimum", + NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.maximum), "Address Maximum", + NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.alignment), "Alignment", + NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.address_length), + "Address Length", NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_fixed_memory32[4] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_fixed_memory32), + "32-Bit Fixed Memory Range", NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(fixed_memory32.write_protect), + "Write Protect", acpi_gbl_rw_decode}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(fixed_memory32.address), "Address", + NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(fixed_memory32.address_length), + "Address Length", NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_address16[8] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_address16), + "16-Bit WORD Address Space", NULL}, + {ACPI_RSD_ADDRESS, 0, NULL, NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.granularity), "Granularity", + NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.minimum), "Address Minimum", + NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.maximum), "Address Maximum", + NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.translation_offset), + "Translation Offset", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.address_length), + "Address Length", NULL}, + {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(address16.resource_source), NULL, NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_address32[8] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_address32), + "32-Bit DWORD Address Space", NULL}, + {ACPI_RSD_ADDRESS, 0, NULL, NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.granularity), "Granularity", + NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.minimum), "Address Minimum", + NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.maximum), "Address Maximum", + NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.translation_offset), + "Translation Offset", NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.address_length), + "Address Length", NULL}, + {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(address32.resource_source), NULL, NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_address64[8] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_address64), + "64-Bit QWORD Address Space", NULL}, + {ACPI_RSD_ADDRESS, 0, NULL, NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.granularity), "Granularity", + NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.minimum), "Address Minimum", + NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.maximum), "Address Maximum", + NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.translation_offset), + "Translation Offset", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.address_length), + "Address Length", NULL}, + {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(address64.resource_source), NULL, NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_ext_address64[8] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_ext_address64), + "64-Bit Extended Address Space", NULL}, + {ACPI_RSD_ADDRESS, 0, NULL, NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.granularity), + "Granularity", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.minimum), + "Address Minimum", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.maximum), + "Address Maximum", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.translation_offset), + "Translation Offset", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.address_length), + "Address Length", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.type_specific), + "Type-Specific Attribute", NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_ext_irq[8] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_ext_irq), + "Extended IRQ", NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.producer_consumer), + "Type", acpi_gbl_consume_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.triggering), + "Triggering", acpi_gbl_he_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.polarity), "Polarity", + acpi_gbl_ll_decode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(extended_irq.sharable), "Sharing", + acpi_gbl_shr_decode}, + {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(extended_irq.resource_source), NULL, + NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(extended_irq.interrupt_count), + "Interrupt Count", NULL}, + {ACPI_RSD_DWORDLIST, ACPI_RSD_OFFSET(extended_irq.interrupts[0]), + "Interrupt List", NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_generic_reg[6] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_generic_reg), + "Generic Register", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(generic_reg.space_id), "Space ID", + NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(generic_reg.bit_width), "Bit Width", + NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(generic_reg.bit_offset), "Bit Offset", + NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(generic_reg.access_size), + "Access Size", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(generic_reg.address), "Address", NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_gpio[16] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_gpio), "GPIO", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(gpio.revision_id), "RevisionId", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(gpio.connection_type), + "ConnectionType", acpi_gbl_ct_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(gpio.producer_consumer), + "ProducerConsumer", acpi_gbl_consume_decode}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(gpio.pin_config), "PinConfig", + acpi_gbl_ppc_decode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(gpio.sharable), "Sharing", + acpi_gbl_shr_decode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(gpio.io_restriction), + "IoRestriction", acpi_gbl_ior_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(gpio.triggering), "Triggering", + acpi_gbl_he_decode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(gpio.polarity), "Polarity", + acpi_gbl_ll_decode}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(gpio.drive_strength), "DriveStrength", + NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(gpio.debounce_timeout), + "DebounceTimeout", NULL}, + {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(gpio.resource_source), + "ResourceSource", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(gpio.pin_table_length), + "PinTableLength", NULL}, + {ACPI_RSD_WORDLIST, ACPI_RSD_OFFSET(gpio.pin_table), "PinTable", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(gpio.vendor_length), "VendorLength", + NULL}, + {ACPI_RSD_SHORTLISTX, ACPI_RSD_OFFSET(gpio.vendor_data), "VendorData", + NULL}, +}; + +struct acpi_rsdump_info acpi_rs_dump_fixed_dma[4] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_fixed_dma), + "FixedDma", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(fixed_dma.request_lines), + "RequestLines", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(fixed_dma.channels), "Channels", + NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(fixed_dma.width), "TransferWidth", + acpi_gbl_dts_decode}, +}; + +#define ACPI_RS_DUMP_COMMON_SERIAL_BUS \ + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (common_serial_bus.revision_id), "RevisionId", NULL}, \ + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (common_serial_bus.type), "Type", acpi_gbl_sbt_decode}, \ + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (common_serial_bus.producer_consumer), "ProducerConsumer", acpi_gbl_consume_decode}, \ + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (common_serial_bus.slave_mode), "SlaveMode", acpi_gbl_sm_decode}, \ + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (common_serial_bus.type_revision_id), "TypeRevisionId", NULL}, \ + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (common_serial_bus.type_data_length), "TypeDataLength", NULL}, \ + {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET (common_serial_bus.resource_source), "ResourceSource", NULL}, \ + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (common_serial_bus.vendor_length), "VendorLength", NULL}, \ + {ACPI_RSD_SHORTLISTX,ACPI_RSD_OFFSET (common_serial_bus.vendor_data), "VendorData", NULL}, + +struct acpi_rsdump_info acpi_rs_dump_common_serial_bus[10] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_common_serial_bus), + "Common Serial Bus", NULL}, + ACPI_RS_DUMP_COMMON_SERIAL_BUS +}; + +struct acpi_rsdump_info acpi_rs_dump_i2c_serial_bus[13] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_i2c_serial_bus), + "I2C Serial Bus", NULL}, + ACPI_RS_DUMP_COMMON_SERIAL_BUS {ACPI_RSD_1BITFLAG, + ACPI_RSD_OFFSET(i2c_serial_bus. + access_mode), + "AccessMode", acpi_gbl_am_decode}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(i2c_serial_bus.connection_speed), + "ConnectionSpeed", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(i2c_serial_bus.slave_address), + "SlaveAddress", NULL}, +}; + +struct acpi_rsdump_info acpi_rs_dump_spi_serial_bus[17] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_spi_serial_bus), + "Spi Serial Bus", NULL}, + ACPI_RS_DUMP_COMMON_SERIAL_BUS {ACPI_RSD_1BITFLAG, + ACPI_RSD_OFFSET(spi_serial_bus. + wire_mode), "WireMode", + acpi_gbl_wm_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(spi_serial_bus.device_polarity), + "DevicePolarity", acpi_gbl_dp_decode}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(spi_serial_bus.data_bit_length), + "DataBitLength", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(spi_serial_bus.clock_phase), + "ClockPhase", acpi_gbl_cph_decode}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(spi_serial_bus.clock_polarity), + "ClockPolarity", acpi_gbl_cpo_decode}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(spi_serial_bus.device_selection), + "DeviceSelection", NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(spi_serial_bus.connection_speed), + "ConnectionSpeed", NULL}, +}; + +struct acpi_rsdump_info acpi_rs_dump_uart_serial_bus[19] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_uart_serial_bus), + "Uart Serial Bus", NULL}, + ACPI_RS_DUMP_COMMON_SERIAL_BUS {ACPI_RSD_2BITFLAG, + ACPI_RSD_OFFSET(uart_serial_bus. + flow_control), + "FlowControl", acpi_gbl_fc_decode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(uart_serial_bus.stop_bits), + "StopBits", acpi_gbl_sb_decode}, + {ACPI_RSD_3BITFLAG, ACPI_RSD_OFFSET(uart_serial_bus.data_bits), + "DataBits", acpi_gbl_bpb_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(uart_serial_bus.endian), "Endian", + acpi_gbl_ed_decode}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(uart_serial_bus.parity), "Parity", + acpi_gbl_pt_decode}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(uart_serial_bus.lines_enabled), + "LinesEnabled", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(uart_serial_bus.rx_fifo_size), + "RxFifoSize", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(uart_serial_bus.tx_fifo_size), + "TxFifoSize", NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(uart_serial_bus.default_baud_rate), + "ConnectionSpeed", NULL}, +}; + +/* + * Tables used for common address descriptor flag fields + */ +struct acpi_rsdump_info acpi_rs_dump_general_flags[5] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_general_flags), NULL, + NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.producer_consumer), + "Consumer/Producer", acpi_gbl_consume_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.decode), "Address Decode", + acpi_gbl_dec_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.min_address_fixed), + "Min Relocatability", acpi_gbl_min_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.max_address_fixed), + "Max Relocatability", acpi_gbl_max_decode} +}; + +struct acpi_rsdump_info acpi_rs_dump_memory_flags[5] = { + {ACPI_RSD_LITERAL, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_memory_flags), + "Resource Type", (void *)"Memory Range"}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.mem.write_protect), + "Write Protect", acpi_gbl_rw_decode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(address.info.mem.caching), + "Caching", acpi_gbl_mem_decode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(address.info.mem.range_type), + "Range Type", acpi_gbl_mtp_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.mem.translation), + "Translation", acpi_gbl_ttp_decode} +}; + +struct acpi_rsdump_info acpi_rs_dump_io_flags[4] = { + {ACPI_RSD_LITERAL, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_io_flags), + "Resource Type", (void *)"I/O Range"}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(address.info.io.range_type), + "Range Type", acpi_gbl_rng_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.io.translation), + "Translation", acpi_gbl_ttp_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.io.translation_type), + "Translation Type", acpi_gbl_trs_decode} +}; + +/* + * Table used to dump _PRT contents + */ +struct acpi_rsdump_info acpi_rs_dump_prt[5] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_prt), NULL, NULL}, + {ACPI_RSD_UINT64, ACPI_PRT_OFFSET(address), "Address", NULL}, + {ACPI_RSD_UINT32, ACPI_PRT_OFFSET(pin), "Pin", NULL}, + {ACPI_RSD_STRING, ACPI_PRT_OFFSET(source[0]), "Source", NULL}, + {ACPI_RSD_UINT32, ACPI_PRT_OFFSET(source_index), "Source Index", NULL} +}; + +#endif diff --git a/drivers/acpi/acpica/rsinfo.c b/drivers/acpi/acpica/rsinfo.c index a9fa5158200b30712155cefbfc9987501cc4142e..41fed78e0de62f84f0d30e74d1560643e28d872a 100644 --- a/drivers/acpi/acpica/rsinfo.c +++ b/drivers/acpi/acpica/rsinfo.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/rsio.c b/drivers/acpi/acpica/rsio.c index f6a081057a22d24ca6e06a40db2df63890eedd45..ca183755a6f9bb3923065906fc00b2d8b82b8a1f 100644 --- a/drivers/acpi/acpica/rsio.c +++ b/drivers/acpi/acpica/rsio.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/rsirq.c b/drivers/acpi/acpica/rsirq.c index e23a9ec248cbc7c8b0e5bfbcc90f1b4d552865b2..364decc1028ac39aa20030a392693eea66ed291b 100644 --- a/drivers/acpi/acpica/rsirq.c +++ b/drivers/acpi/acpica/rsirq.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -53,7 +53,7 @@ ACPI_MODULE_NAME("rsirq") * acpi_rs_get_irq * ******************************************************************************/ -struct acpi_rsconvert_info acpi_rs_get_irq[8] = { +struct acpi_rsconvert_info acpi_rs_get_irq[9] = { {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_IRQ, ACPI_RS_SIZE(struct acpi_resource_irq), ACPI_RSC_TABLE_SIZE(acpi_rs_get_irq)}, @@ -80,7 +80,7 @@ struct acpi_rsconvert_info acpi_rs_get_irq[8] = { {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_AML_LENGTH, 0, 3}, - /* Get flags: Triggering[0], Polarity[3], Sharing[4] */ + /* Get flags: Triggering[0], Polarity[3], Sharing[4], Wake[5] */ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.triggering), AML_OFFSET(irq.flags), @@ -92,7 +92,11 @@ struct acpi_rsconvert_info acpi_rs_get_irq[8] = { {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.sharable), AML_OFFSET(irq.flags), - 4} + 4}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.wake_capable), + AML_OFFSET(irq.flags), + 5} }; /******************************************************************************* @@ -101,7 +105,7 @@ struct acpi_rsconvert_info acpi_rs_get_irq[8] = { * ******************************************************************************/ -struct acpi_rsconvert_info acpi_rs_set_irq[13] = { +struct acpi_rsconvert_info acpi_rs_set_irq[14] = { /* Start with a default descriptor of length 3 */ {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_IRQ, @@ -114,7 +118,7 @@ struct acpi_rsconvert_info acpi_rs_set_irq[13] = { AML_OFFSET(irq.irq_mask), ACPI_RS_OFFSET(data.irq.interrupt_count)}, - /* Set the flags byte */ + /* Set flags: Triggering[0], Polarity[3], Sharing[4], Wake[5] */ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.triggering), AML_OFFSET(irq.flags), @@ -128,6 +132,10 @@ struct acpi_rsconvert_info acpi_rs_set_irq[13] = { AML_OFFSET(irq.flags), 4}, + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.wake_capable), + AML_OFFSET(irq.flags), + 5}, + /* * All done if the output descriptor length is required to be 3 * (i.e., optimization to 2 bytes cannot be attempted) @@ -181,7 +189,7 @@ struct acpi_rsconvert_info acpi_rs_set_irq[13] = { * ******************************************************************************/ -struct acpi_rsconvert_info acpi_rs_convert_ext_irq[9] = { +struct acpi_rsconvert_info acpi_rs_convert_ext_irq[10] = { {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_EXTENDED_IRQ, ACPI_RS_SIZE(struct acpi_resource_extended_irq), ACPI_RSC_TABLE_SIZE(acpi_rs_convert_ext_irq)}, @@ -190,8 +198,10 @@ struct acpi_rsconvert_info acpi_rs_convert_ext_irq[9] = { sizeof(struct aml_resource_extended_irq), 0}, - /* Flag bits */ - + /* + * Flags: Producer/Consumer[0], Triggering[1], Polarity[2], + * Sharing[3], Wake[4] + */ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.extended_irq.producer_consumer), AML_OFFSET(extended_irq.flags), 0}, @@ -208,19 +218,21 @@ struct acpi_rsconvert_info acpi_rs_convert_ext_irq[9] = { AML_OFFSET(extended_irq.flags), 3}, + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.extended_irq.wake_capable), + AML_OFFSET(extended_irq.flags), + 4}, + /* IRQ Table length (Byte4) */ {ACPI_RSC_COUNT, ACPI_RS_OFFSET(data.extended_irq.interrupt_count), AML_OFFSET(extended_irq.interrupt_count), - sizeof(u32)} - , + sizeof(u32)}, /* Copy every IRQ in the table, each is 32 bits */ {ACPI_RSC_MOVE32, ACPI_RS_OFFSET(data.extended_irq.interrupts[0]), AML_OFFSET(extended_irq.interrupts[0]), - 0} - , + 0}, /* Optional resource_source (Index and String) */ @@ -285,7 +297,6 @@ struct acpi_rsconvert_info acpi_rs_convert_fixed_dma[4] = { * request_lines * Channels */ - {ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.fixed_dma.request_lines), AML_OFFSET(fixed_dma.request_lines), 2}, @@ -293,5 +304,4 @@ struct acpi_rsconvert_info acpi_rs_convert_fixed_dma[4] = { {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.fixed_dma.width), AML_OFFSET(fixed_dma.width), 1}, - }; diff --git a/drivers/acpi/acpica/rslist.c b/drivers/acpi/acpica/rslist.c index 8b64db9a3fd2cd6a8a465ba666c710c66b634d86..ee2e206fc6c8e8dbad901ad67653cd7d697e2273 100644 --- a/drivers/acpi/acpica/rslist.c +++ b/drivers/acpi/acpica/rslist.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -217,9 +217,10 @@ acpi_rs_convert_resources_to_aml(struct acpi_resource *resource, /* Perform final sanity check on the new AML resource descriptor */ - status = - acpi_ut_validate_resource(ACPI_CAST_PTR - (union aml_resource, aml), NULL); + status = acpi_ut_validate_resource(NULL, + ACPI_CAST_PTR(union + aml_resource, + aml), NULL); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/rsmemory.c b/drivers/acpi/acpica/rsmemory.c index 4fd611ad02b48d9d706cfe886d347c345f2bbdda..ebc773a1b350b4386cb3896f464efe957e9a379d 100644 --- a/drivers/acpi/acpica/rsmemory.c +++ b/drivers/acpi/acpica/rsmemory.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -156,8 +156,7 @@ struct acpi_rsconvert_info acpi_rs_get_vendor_small[3] = { {ACPI_RSC_COUNT16, ACPI_RS_OFFSET(data.vendor.byte_length), 0, - sizeof(u8)} - , + sizeof(u8)}, /* Vendor data */ @@ -181,8 +180,7 @@ struct acpi_rsconvert_info acpi_rs_get_vendor_large[3] = { {ACPI_RSC_COUNT16, ACPI_RS_OFFSET(data.vendor.byte_length), 0, - sizeof(u8)} - , + sizeof(u8)}, /* Vendor data */ diff --git a/drivers/acpi/acpica/rsmisc.c b/drivers/acpi/acpica/rsmisc.c index c6f291c2bc8355e5ccb7a7d1a0c25f593448fab8..d5bf05a96096ad785897966876929b02dba60c02 100644 --- a/drivers/acpi/acpica/rsmisc.c +++ b/drivers/acpi/acpica/rsmisc.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -136,30 +136,30 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, /* * Mask and shift the flag bit */ - ACPI_SET8(destination) = (u8) - ((ACPI_GET8(source) >> info->value) & 0x01); + ACPI_SET8(destination, + ((ACPI_GET8(source) >> info->value) & 0x01)); break; case ACPI_RSC_2BITFLAG: /* * Mask and shift the flag bits */ - ACPI_SET8(destination) = (u8) - ((ACPI_GET8(source) >> info->value) & 0x03); + ACPI_SET8(destination, + ((ACPI_GET8(source) >> info->value) & 0x03)); break; case ACPI_RSC_3BITFLAG: /* * Mask and shift the flag bits */ - ACPI_SET8(destination) = (u8) - ((ACPI_GET8(source) >> info->value) & 0x07); + ACPI_SET8(destination, + ((ACPI_GET8(source) >> info->value) & 0x07)); break; case ACPI_RSC_COUNT: item_count = ACPI_GET8(source); - ACPI_SET8(destination) = (u8) item_count; + ACPI_SET8(destination, item_count); resource->length = resource->length + (info->value * (item_count - 1)); @@ -168,7 +168,7 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, case ACPI_RSC_COUNT16: item_count = aml_resource_length; - ACPI_SET16(destination) = item_count; + ACPI_SET16(destination, item_count); resource->length = resource->length + (info->value * (item_count - 1)); @@ -181,13 +181,13 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, resource->length = resource->length + item_count; item_count = item_count / 2; - ACPI_SET16(destination) = item_count; + ACPI_SET16(destination, item_count); break; case ACPI_RSC_COUNT_GPIO_VEN: item_count = ACPI_GET8(source); - ACPI_SET8(destination) = (u8)item_count; + ACPI_SET8(destination, item_count); resource->length = resource->length + (info->value * item_count); @@ -216,7 +216,7 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, } resource->length = resource->length + item_count; - ACPI_SET16(destination) = item_count; + ACPI_SET16(destination, item_count); break; case ACPI_RSC_COUNT_SERIAL_VEN: @@ -224,7 +224,7 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, item_count = ACPI_GET16(source) - info->value; resource->length = resource->length + item_count; - ACPI_SET16(destination) = item_count; + ACPI_SET16(destination, item_count); break; case ACPI_RSC_COUNT_SERIAL_RES: @@ -234,7 +234,7 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, - ACPI_GET16(source) - info->value; resource->length = resource->length + item_count; - ACPI_SET16(destination) = item_count; + ACPI_SET16(destination, item_count); break; case ACPI_RSC_LENGTH: @@ -385,7 +385,7 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, } target = ACPI_ADD_PTR(char, resource, info->value); - ACPI_SET8(target) = (u8) item_count; + ACPI_SET8(target, item_count); break; case ACPI_RSC_BITMASK16: @@ -401,7 +401,7 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, } target = ACPI_ADD_PTR(char, resource, info->value); - ACPI_SET8(target) = (u8) item_count; + ACPI_SET8(target, item_count); break; case ACPI_RSC_EXIT_NE: @@ -514,37 +514,40 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, /* * Clear the flag byte */ - ACPI_SET8(destination) = 0; + ACPI_SET8(destination, 0); break; case ACPI_RSC_1BITFLAG: /* * Mask and shift the flag bit */ - ACPI_SET8(destination) |= (u8) - ((ACPI_GET8(source) & 0x01) << info->value); + ACPI_SET_BIT(*ACPI_CAST8(destination), (u8) + ((ACPI_GET8(source) & 0x01) << info-> + value)); break; case ACPI_RSC_2BITFLAG: /* * Mask and shift the flag bits */ - ACPI_SET8(destination) |= (u8) - ((ACPI_GET8(source) & 0x03) << info->value); + ACPI_SET_BIT(*ACPI_CAST8(destination), (u8) + ((ACPI_GET8(source) & 0x03) << info-> + value)); break; case ACPI_RSC_3BITFLAG: /* * Mask and shift the flag bits */ - ACPI_SET8(destination) |= (u8) - ((ACPI_GET8(source) & 0x07) << info->value); + ACPI_SET_BIT(*ACPI_CAST8(destination), (u8) + ((ACPI_GET8(source) & 0x07) << info-> + value)); break; case ACPI_RSC_COUNT: item_count = ACPI_GET8(source); - ACPI_SET8(destination) = (u8) item_count; + ACPI_SET8(destination, item_count); aml_length = (u16) (aml_length + @@ -561,18 +564,18 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, case ACPI_RSC_COUNT_GPIO_PIN: item_count = ACPI_GET16(source); - ACPI_SET16(destination) = (u16)aml_length; + ACPI_SET16(destination, aml_length); aml_length = (u16)(aml_length + item_count * 2); target = ACPI_ADD_PTR(void, aml, info->value); - ACPI_SET16(target) = (u16)aml_length; + ACPI_SET16(target, aml_length); acpi_rs_set_resource_length(aml_length, aml); break; case ACPI_RSC_COUNT_GPIO_VEN: item_count = ACPI_GET16(source); - ACPI_SET16(destination) = (u16)item_count; + ACPI_SET16(destination, item_count); aml_length = (u16)(aml_length + (info->value * item_count)); @@ -584,7 +587,7 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, /* Set resource source string length */ item_count = ACPI_GET16(source); - ACPI_SET16(destination) = (u16)aml_length; + ACPI_SET16(destination, aml_length); /* Compute offset for the Vendor Data */ @@ -594,7 +597,7 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, /* Set vendor offset only if there is vendor data */ if (resource->data.gpio.vendor_length) { - ACPI_SET16(target) = (u16)aml_length; + ACPI_SET16(target, aml_length); } acpi_rs_set_resource_length(aml_length, aml); @@ -603,7 +606,7 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, case ACPI_RSC_COUNT_SERIAL_VEN: item_count = ACPI_GET16(source); - ACPI_SET16(destination) = item_count + info->value; + ACPI_SET16(destination, item_count + info->value); aml_length = (u16)(aml_length + item_count); acpi_rs_set_resource_length(aml_length, aml); break; @@ -686,7 +689,8 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, * Optional resource_source (Index and String) */ aml_length = - acpi_rs_set_resource_source(aml, (acpi_rs_length) + acpi_rs_set_resource_source(aml, + (acpi_rs_length) aml_length, source); acpi_rs_set_resource_length(aml_length, aml); break; @@ -706,10 +710,12 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, /* * 8-bit encoded bitmask (DMA macro) */ - ACPI_SET8(destination) = (u8) - acpi_rs_encode_bitmask(source, - *ACPI_ADD_PTR(u8, resource, - info->value)); + ACPI_SET8(destination, + acpi_rs_encode_bitmask(source, + *ACPI_ADD_PTR(u8, + resource, + info-> + value))); break; case ACPI_RSC_BITMASK16: diff --git a/drivers/acpi/acpica/rsserial.c b/drivers/acpi/acpica/rsserial.c index 9aa5e689b4441cf244d4d08ce780f21e14bffa94..fe49fc43e10f54b726debec50b6f4c54c4cd24a9 100644 --- a/drivers/acpi/acpica/rsserial.c +++ b/drivers/acpi/acpica/rsserial.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -53,7 +53,7 @@ ACPI_MODULE_NAME("rsserial") * acpi_rs_convert_gpio * ******************************************************************************/ -struct acpi_rsconvert_info acpi_rs_convert_gpio[17] = { +struct acpi_rsconvert_info acpi_rs_convert_gpio[18] = { {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_GPIO, ACPI_RS_SIZE(struct acpi_resource_gpio), ACPI_RSC_TABLE_SIZE(acpi_rs_convert_gpio)}, @@ -75,10 +75,14 @@ struct acpi_rsconvert_info acpi_rs_convert_gpio[17] = { AML_OFFSET(gpio.flags), 0}, - {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.gpio.sharable), + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.gpio.sharable), AML_OFFSET(gpio.int_flags), 3}, + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.gpio.wake_capable), + AML_OFFSET(gpio.int_flags), + 4}, + {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.gpio.io_restriction), AML_OFFSET(gpio.int_flags), 0}, diff --git a/drivers/acpi/acpica/rsutils.c b/drivers/acpi/acpica/rsutils.c index 37d5241c0acf731d2581bb51f68c84f5ae4643d5..a44953c6f75da74d7c0e160078eff90b5abfc5ba 100644 --- a/drivers/acpi/acpica/rsutils.c +++ b/drivers/acpi/acpica/rsutils.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -108,7 +108,7 @@ u16 acpi_rs_encode_bitmask(u8 * list, u8 count) mask |= (0x1 << list[i]); } - return mask; + return (mask); } /******************************************************************************* @@ -358,8 +358,10 @@ acpi_rs_get_resource_source(acpi_rs_length resource_length, * * Zero the entire area of the buffer. */ - total_length = (u32) - ACPI_STRLEN(ACPI_CAST_PTR(char, &aml_resource_source[1])) + 1; + total_length = + (u32) + ACPI_STRLEN(ACPI_CAST_PTR(char, &aml_resource_source[1])) + + 1; total_length = (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(total_length); ACPI_MEMSET(resource_source->string_ptr, 0, total_length); @@ -675,7 +677,9 @@ acpi_rs_get_method_data(acpi_handle handle, /* Execute the method, no parameters */ status = - acpi_ut_evaluate_object(handle, path, ACPI_BTYPE_BUFFER, &obj_desc); + acpi_ut_evaluate_object(ACPI_CAST_PTR + (struct acpi_namespace_node, handle), path, + ACPI_BTYPE_BUFFER, &obj_desc); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/rsxface.c b/drivers/acpi/acpica/rsxface.c index 5aad744b5b833088323352110020c8c316abcd3d..15d6eaef0e286a21f01d9eee5636e46d7e75c5e2 100644 --- a/drivers/acpi/acpica/rsxface.c +++ b/drivers/acpi/acpica/rsxface.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -423,7 +423,7 @@ ACPI_EXPORT_SYMBOL(acpi_resource_to_address64) * * RETURN: Status * - * DESCRIPTION: Walk a resource template for the specified evice to find a + * DESCRIPTION: Walk a resource template for the specified device to find a * vendor-defined resource that matches the supplied UUID and * UUID subtype. Returns a struct acpi_resource of type Vendor. * @@ -522,57 +522,42 @@ acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context) /******************************************************************************* * - * FUNCTION: acpi_walk_resources + * FUNCTION: acpi_walk_resource_buffer * - * PARAMETERS: device_handle - Handle to the device object for the - * device we are querying - * name - Method name of the resources we want. - * (METHOD_NAME__CRS, METHOD_NAME__PRS, or - * METHOD_NAME__AEI) + * PARAMETERS: buffer - Formatted buffer returned by one of the + * various Get*Resource functions * user_function - Called for each resource * context - Passed to user_function * * RETURN: Status * - * DESCRIPTION: Retrieves the current or possible resource list for the - * specified device. The user_function is called once for - * each resource in the list. + * DESCRIPTION: Walks the input resource template. The user_function is called + * once for each resource in the list. * ******************************************************************************/ + acpi_status -acpi_walk_resources(acpi_handle device_handle, - char *name, - acpi_walk_resource_callback user_function, void *context) +acpi_walk_resource_buffer(struct acpi_buffer * buffer, + acpi_walk_resource_callback user_function, + void *context) { - acpi_status status; - struct acpi_buffer buffer; + acpi_status status = AE_OK; struct acpi_resource *resource; struct acpi_resource *resource_end; - ACPI_FUNCTION_TRACE(acpi_walk_resources); + ACPI_FUNCTION_TRACE(acpi_walk_resource_buffer); /* Parameter validation */ - if (!device_handle || !user_function || !name || - (!ACPI_COMPARE_NAME(name, METHOD_NAME__CRS) && - !ACPI_COMPARE_NAME(name, METHOD_NAME__PRS) && - !ACPI_COMPARE_NAME(name, METHOD_NAME__AEI))) { + if (!buffer || !buffer->pointer || !user_function) { return_ACPI_STATUS(AE_BAD_PARAMETER); } - /* Get the _CRS/_PRS/_AEI resource list */ - - buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; - status = acpi_rs_get_method_data(device_handle, name, &buffer); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Buffer now contains the resource list */ + /* Buffer contains the resource list and length */ - resource = ACPI_CAST_PTR(struct acpi_resource, buffer.pointer); + resource = ACPI_CAST_PTR(struct acpi_resource, buffer->pointer); resource_end = - ACPI_ADD_PTR(struct acpi_resource, buffer.pointer, buffer.length); + ACPI_ADD_PTR(struct acpi_resource, buffer->pointer, buffer->length); /* Walk the resource list until the end_tag is found (or buffer end) */ @@ -606,11 +591,63 @@ acpi_walk_resources(acpi_handle device_handle, /* Get the next resource descriptor */ - resource = - ACPI_ADD_PTR(struct acpi_resource, resource, - resource->length); + resource = ACPI_NEXT_RESOURCE(resource); } + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_walk_resource_buffer) + +/******************************************************************************* + * + * FUNCTION: acpi_walk_resources + * + * PARAMETERS: device_handle - Handle to the device object for the + * device we are querying + * name - Method name of the resources we want. + * (METHOD_NAME__CRS, METHOD_NAME__PRS, or + * METHOD_NAME__AEI) + * user_function - Called for each resource + * context - Passed to user_function + * + * RETURN: Status + * + * DESCRIPTION: Retrieves the current or possible resource list for the + * specified device. The user_function is called once for + * each resource in the list. + * + ******************************************************************************/ +acpi_status +acpi_walk_resources(acpi_handle device_handle, + char *name, + acpi_walk_resource_callback user_function, void *context) +{ + acpi_status status; + struct acpi_buffer buffer; + + ACPI_FUNCTION_TRACE(acpi_walk_resources); + + /* Parameter validation */ + + if (!device_handle || !user_function || !name || + (!ACPI_COMPARE_NAME(name, METHOD_NAME__CRS) && + !ACPI_COMPARE_NAME(name, METHOD_NAME__PRS) && + !ACPI_COMPARE_NAME(name, METHOD_NAME__AEI))) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* Get the _CRS/_PRS/_AEI resource list */ + + buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; + status = acpi_rs_get_method_data(device_handle, name, &buffer); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Walk the resource list and cleanup */ + + status = acpi_walk_resource_buffer(&buffer, user_function, context); ACPI_FREE(buffer.pointer); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c index 390651860bf09580f62787758e4ba1b76a80944a..74181bf181ec94112a1ec8d39ebd64b6f43466a3 100644 --- a/drivers/acpi/acpica/tbfadt.c +++ b/drivers/acpi/acpica/tbfadt.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -172,6 +172,7 @@ static struct acpi_fadt_pm_info fadt_pm_info_table[] = { * FUNCTION: acpi_tb_init_generic_address * * PARAMETERS: generic_address - GAS struct to be initialized + * space_id - ACPI Space ID for this register * byte_width - Width of this register * address - Address of the register * @@ -407,8 +408,8 @@ static void acpi_tb_convert_fadt(void) * should be zero are indeed zero. This will workaround BIOSs that * inadvertently place values in these fields. * - * The ACPI 1.0 reserved fields that will be zeroed are the bytes located at - * offset 45, 55, 95, and the word located at offset 109, 110. + * The ACPI 1.0 reserved fields that will be zeroed are the bytes located + * at offset 45, 55, 95, and the word located at offset 109, 110. * * Note: The FADT revision value is unreliable. Only the length can be * trusted. diff --git a/drivers/acpi/acpica/tbfind.c b/drivers/acpi/acpica/tbfind.c index 77d1db29a725ea8183b1733a15e712349c10e7dd..e4f4f02d49e7cf58f4acc9db842d741bb46a9301 100644 --- a/drivers/acpi/acpica/tbfind.c +++ b/drivers/acpi/acpica/tbfind.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/tbinstal.c b/drivers/acpi/acpica/tbinstal.c index f540ae462925eff4614da3caf47e213d4591d938..e57cd38004e33c3adb3b7850bc25b4f23f577430 100644 --- a/drivers/acpi/acpica/tbinstal.c +++ b/drivers/acpi/acpica/tbinstal.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c index 285e24b973822812d069721aeb44acc9908229f0..ce3d5db39a9c742d49fc7aa9103121942da73c6a 100644 --- a/drivers/acpi/acpica/tbutils.c +++ b/drivers/acpi/acpica/tbutils.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -147,7 +147,7 @@ acpi_status acpi_tb_initialize_facs(void) ACPI_CAST_INDIRECT_PTR(struct acpi_table_header, &acpi_gbl_FACS)); - return status; + return (status); } #endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c index f5632780421d2ab7bd30c14c6948e8d9b893d303..b35a5e6d653a9c32678a6a3811cccb326bccddd2 100644 --- a/drivers/acpi/acpica/tbxface.c +++ b/drivers/acpi/acpica/tbxface.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,7 +44,6 @@ #include #include #include "accommon.h" -#include "acnamesp.h" #include "actables.h" #define _COMPONENT ACPI_TABLES @@ -437,7 +436,7 @@ ACPI_EXPORT_SYMBOL(acpi_get_table_by_index) * ******************************************************************************/ acpi_status -acpi_install_table_handler(acpi_tbl_handler handler, void *context) +acpi_install_table_handler(acpi_table_handler handler, void *context) { acpi_status status; @@ -483,7 +482,7 @@ ACPI_EXPORT_SYMBOL(acpi_install_table_handler) * DESCRIPTION: Remove table event handler * ******************************************************************************/ -acpi_status acpi_remove_table_handler(acpi_tbl_handler handler) +acpi_status acpi_remove_table_handler(acpi_table_handler handler) { acpi_status status; diff --git a/drivers/acpi/acpica/tbxfload.c b/drivers/acpi/acpica/tbxfload.c index a5e1e4e47098979ac2d8eccbd520fe77ba9fd86b..67e046ec8f0afaedfec54d273b3193a9cffbb63a 100644 --- a/drivers/acpi/acpica/tbxfload.c +++ b/drivers/acpi/acpica/tbxfload.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -192,7 +192,7 @@ static acpi_status acpi_tb_load_namespace(void) (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); } - ACPI_DEBUG_PRINT((ACPI_DB_INIT, "ACPI Tables successfully acquired\n")); + ACPI_INFO((AE_INFO, "All ACPI Tables successfully acquired")); unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); diff --git a/drivers/acpi/acpica/tbxfroot.c b/drivers/acpi/acpica/tbxfroot.c index 28f330230f999026cca544d72e6b6c3ee431f0a4..7c2ecfb7c2c37dbb448e7703d2689d994fe8931f 100644 --- a/drivers/acpi/acpica/tbxfroot.c +++ b/drivers/acpi/acpica/tbxfroot.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utaddress.c b/drivers/acpi/acpica/utaddress.c index 64880306133d9156b5862812b12ff018ef48a59d..698b9d385516eb98b73d052acee693f1764eb745 100644 --- a/drivers/acpi/acpica/utaddress.c +++ b/drivers/acpi/acpica/utaddress.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -214,7 +214,7 @@ acpi_ut_check_address_range(acpi_adr_space_type space_id, if ((space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) && (space_id != ACPI_ADR_SPACE_SYSTEM_IO)) { - return_UINT32(0); + return_VALUE(0); } range_info = acpi_gbl_address_range_list[space_id]; @@ -256,7 +256,7 @@ acpi_ut_check_address_range(acpi_adr_space_type space_id, range_info = range_info->next; } - return_UINT32(overlap_count); + return_VALUE(overlap_count); } /******************************************************************************* diff --git a/drivers/acpi/acpica/utalloc.c b/drivers/acpi/acpica/utalloc.c index ed29d474095e9b2b64565f4c7934b848a3ed7a8f..e0ffb580f4b06eba27e05ad03bc55e47f9654ff6 100644 --- a/drivers/acpi/acpica/utalloc.c +++ b/drivers/acpi/acpica/utalloc.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utcache.c b/drivers/acpi/acpica/utcache.c index e1d40ed263901c131f65eb839802c43abb7d2043..e0e8579deaacf19a0cc35997191bd79a0ea479c1 100644 --- a/drivers/acpi/acpica/utcache.c +++ b/drivers/acpi/acpica/utcache.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utcopy.c b/drivers/acpi/acpica/utcopy.c index 294692ae76e918e25ab56e43b36b86d26950ea00..e4c9291fc0a3f530bfaea472895f6217a23f8b99 100644 --- a/drivers/acpi/acpica/utcopy.c +++ b/drivers/acpi/acpica/utcopy.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -785,7 +785,7 @@ acpi_ut_copy_simple_object(union acpi_operand_object *source_desc, status = acpi_os_create_mutex(&dest_desc->mutex.os_mutex); if (ACPI_FAILURE(status)) { - return status; + return (status); } break; @@ -795,7 +795,7 @@ acpi_ut_copy_simple_object(union acpi_operand_object *source_desc, &dest_desc->event. os_semaphore); if (ACPI_FAILURE(status)) { - return status; + return (status); } break; diff --git a/drivers/acpi/acpica/utdebug.c b/drivers/acpi/acpica/utdebug.c index 5d95166245ae9dbae0cfba65553541c5a28a6601..c57d9cc07ba913c9576792f395ffcea08a76fc03 100644 --- a/drivers/acpi/acpica/utdebug.c +++ b/drivers/acpi/acpica/utdebug.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -166,11 +166,9 @@ acpi_debug_print(u32 requested_debug_level, acpi_thread_id thread_id; va_list args; - /* - * Stay silent if the debug level or component ID is disabled - */ - if (!(requested_debug_level & acpi_dbg_level) || - !(component_id & acpi_dbg_layer)) { + /* Check if debug output enabled */ + + if (!ACPI_IS_DEBUG_ENABLED(requested_debug_level, component_id)) { return; } @@ -236,8 +234,9 @@ acpi_debug_print_raw(u32 requested_debug_level, { va_list args; - if (!(requested_debug_level & acpi_dbg_level) || - !(component_id & acpi_dbg_layer)) { + /* Check if debug output enabled */ + + if (!ACPI_IS_DEBUG_ENABLED(requested_debug_level, component_id)) { return; } @@ -272,9 +271,13 @@ acpi_ut_trace(u32 line_number, acpi_gbl_nesting_level++; acpi_ut_track_stack_ptr(); - acpi_debug_print(ACPI_LV_FUNCTIONS, - line_number, function_name, module_name, component_id, - "%s\n", acpi_gbl_fn_entry_str); + /* Check if enabled up-front for performance */ + + if (ACPI_IS_DEBUG_ENABLED(ACPI_LV_FUNCTIONS, component_id)) { + acpi_debug_print(ACPI_LV_FUNCTIONS, + line_number, function_name, module_name, + component_id, "%s\n", acpi_gbl_fn_entry_str); + } } ACPI_EXPORT_SYMBOL(acpi_ut_trace) @@ -304,9 +307,14 @@ acpi_ut_trace_ptr(u32 line_number, acpi_gbl_nesting_level++; acpi_ut_track_stack_ptr(); - acpi_debug_print(ACPI_LV_FUNCTIONS, - line_number, function_name, module_name, component_id, - "%s %p\n", acpi_gbl_fn_entry_str, pointer); + /* Check if enabled up-front for performance */ + + if (ACPI_IS_DEBUG_ENABLED(ACPI_LV_FUNCTIONS, component_id)) { + acpi_debug_print(ACPI_LV_FUNCTIONS, + line_number, function_name, module_name, + component_id, "%s %p\n", acpi_gbl_fn_entry_str, + pointer); + } } /******************************************************************************* @@ -335,9 +343,14 @@ acpi_ut_trace_str(u32 line_number, acpi_gbl_nesting_level++; acpi_ut_track_stack_ptr(); - acpi_debug_print(ACPI_LV_FUNCTIONS, - line_number, function_name, module_name, component_id, - "%s %s\n", acpi_gbl_fn_entry_str, string); + /* Check if enabled up-front for performance */ + + if (ACPI_IS_DEBUG_ENABLED(ACPI_LV_FUNCTIONS, component_id)) { + acpi_debug_print(ACPI_LV_FUNCTIONS, + line_number, function_name, module_name, + component_id, "%s %s\n", acpi_gbl_fn_entry_str, + string); + } } /******************************************************************************* @@ -366,9 +379,14 @@ acpi_ut_trace_u32(u32 line_number, acpi_gbl_nesting_level++; acpi_ut_track_stack_ptr(); - acpi_debug_print(ACPI_LV_FUNCTIONS, - line_number, function_name, module_name, component_id, - "%s %08X\n", acpi_gbl_fn_entry_str, integer); + /* Check if enabled up-front for performance */ + + if (ACPI_IS_DEBUG_ENABLED(ACPI_LV_FUNCTIONS, component_id)) { + acpi_debug_print(ACPI_LV_FUNCTIONS, + line_number, function_name, module_name, + component_id, "%s %08X\n", + acpi_gbl_fn_entry_str, integer); + } } /******************************************************************************* @@ -393,9 +411,13 @@ acpi_ut_exit(u32 line_number, const char *module_name, u32 component_id) { - acpi_debug_print(ACPI_LV_FUNCTIONS, - line_number, function_name, module_name, component_id, - "%s\n", acpi_gbl_fn_exit_str); + /* Check if enabled up-front for performance */ + + if (ACPI_IS_DEBUG_ENABLED(ACPI_LV_FUNCTIONS, component_id)) { + acpi_debug_print(ACPI_LV_FUNCTIONS, + line_number, function_name, module_name, + component_id, "%s\n", acpi_gbl_fn_exit_str); + } acpi_gbl_nesting_level--; } @@ -425,17 +447,23 @@ acpi_ut_status_exit(u32 line_number, u32 component_id, acpi_status status) { - if (ACPI_SUCCESS(status)) { - acpi_debug_print(ACPI_LV_FUNCTIONS, - line_number, function_name, module_name, - component_id, "%s %s\n", acpi_gbl_fn_exit_str, - acpi_format_exception(status)); - } else { - acpi_debug_print(ACPI_LV_FUNCTIONS, - line_number, function_name, module_name, - component_id, "%s ****Exception****: %s\n", - acpi_gbl_fn_exit_str, - acpi_format_exception(status)); + /* Check if enabled up-front for performance */ + + if (ACPI_IS_DEBUG_ENABLED(ACPI_LV_FUNCTIONS, component_id)) { + if (ACPI_SUCCESS(status)) { + acpi_debug_print(ACPI_LV_FUNCTIONS, + line_number, function_name, + module_name, component_id, "%s %s\n", + acpi_gbl_fn_exit_str, + acpi_format_exception(status)); + } else { + acpi_debug_print(ACPI_LV_FUNCTIONS, + line_number, function_name, + module_name, component_id, + "%s ****Exception****: %s\n", + acpi_gbl_fn_exit_str, + acpi_format_exception(status)); + } } acpi_gbl_nesting_level--; @@ -465,10 +493,15 @@ acpi_ut_value_exit(u32 line_number, const char *module_name, u32 component_id, u64 value) { - acpi_debug_print(ACPI_LV_FUNCTIONS, - line_number, function_name, module_name, component_id, - "%s %8.8X%8.8X\n", acpi_gbl_fn_exit_str, - ACPI_FORMAT_UINT64(value)); + /* Check if enabled up-front for performance */ + + if (ACPI_IS_DEBUG_ENABLED(ACPI_LV_FUNCTIONS, component_id)) { + acpi_debug_print(ACPI_LV_FUNCTIONS, + line_number, function_name, module_name, + component_id, "%s %8.8X%8.8X\n", + acpi_gbl_fn_exit_str, + ACPI_FORMAT_UINT64(value)); + } acpi_gbl_nesting_level--; } @@ -497,9 +530,14 @@ acpi_ut_ptr_exit(u32 line_number, const char *module_name, u32 component_id, u8 *ptr) { - acpi_debug_print(ACPI_LV_FUNCTIONS, - line_number, function_name, module_name, component_id, - "%s %p\n", acpi_gbl_fn_exit_str, ptr); + /* Check if enabled up-front for performance */ + + if (ACPI_IS_DEBUG_ENABLED(ACPI_LV_FUNCTIONS, component_id)) { + acpi_debug_print(ACPI_LV_FUNCTIONS, + line_number, function_name, module_name, + component_id, "%s %p\n", acpi_gbl_fn_exit_str, + ptr); + } acpi_gbl_nesting_level--; } diff --git a/drivers/acpi/acpica/utdecode.c b/drivers/acpi/acpica/utdecode.c index 60a158472d820ac7e8aeba53c77634674a8ee747..11e2e02e1618702dc75b6371d83f6da257edba61 100644 --- a/drivers/acpi/acpica/utdecode.c +++ b/drivers/acpi/acpica/utdecode.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utdelete.c b/drivers/acpi/acpica/utdelete.c index 798105443d0f9c4689d26641ff7d206a63e56f1c..2541de4202498944e8c015b702112d1493e878a8 100644 --- a/drivers/acpi/acpica/utdelete.c +++ b/drivers/acpi/acpica/utdelete.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -340,7 +340,7 @@ void acpi_ut_delete_internal_object_list(union acpi_operand_object **obj_list) { union acpi_operand_object **internal_obj; - ACPI_FUNCTION_TRACE(ut_delete_internal_object_list); + ACPI_FUNCTION_ENTRY(); /* Walk the null-terminated internal list */ @@ -351,7 +351,7 @@ void acpi_ut_delete_internal_object_list(union acpi_operand_object **obj_list) /* Free the combined parameter pointer list and object array */ ACPI_FREE(obj_list); - return_VOID; + return; } /******************************************************************************* @@ -484,7 +484,7 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) union acpi_generic_state *state; u32 i; - ACPI_FUNCTION_TRACE_PTR(ut_update_object_reference, object); + ACPI_FUNCTION_NAME(ut_update_object_reference); while (object) { @@ -493,7 +493,7 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) if (ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_NAMED) { ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Object %p is NS handle\n", object)); - return_ACPI_STATUS(AE_OK); + return (AE_OK); } /* @@ -530,18 +530,42 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) */ for (i = 0; i < object->package.count; i++) { /* - * Push each element onto the stack for later processing. - * Note: There can be null elements within the package, - * these are simply ignored + * Null package elements are legal and can be simply + * ignored. */ - status = - acpi_ut_create_update_state_and_push - (object->package.elements[i], action, - &state_list); - if (ACPI_FAILURE(status)) { - goto error_exit; + next_object = object->package.elements[i]; + if (!next_object) { + continue; + } + + switch (next_object->common.type) { + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + /* + * For these very simple sub-objects, we can just + * update the reference count here and continue. + * Greatly increases performance of this operation. + */ + acpi_ut_update_ref_count(next_object, + action); + break; + + default: + /* + * For complex sub-objects, push them onto the stack + * for later processing (this eliminates recursion.) + */ + status = + acpi_ut_create_update_state_and_push + (next_object, action, &state_list); + if (ACPI_FAILURE(status)) { + goto error_exit; + } + break; } } + next_object = NULL; break; case ACPI_TYPE_BUFFER_FIELD: @@ -619,7 +643,7 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) } } - return_ACPI_STATUS(AE_OK); + return (AE_OK); error_exit: @@ -633,7 +657,7 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) acpi_ut_delete_generic_state(state); } - return_ACPI_STATUS(status); + return (status); } /******************************************************************************* @@ -652,12 +676,12 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) void acpi_ut_add_reference(union acpi_operand_object *object) { - ACPI_FUNCTION_TRACE_PTR(ut_add_reference, object); + ACPI_FUNCTION_NAME(ut_add_reference); /* Ensure that we have a valid object */ if (!acpi_ut_valid_internal_object(object)) { - return_VOID; + return; } ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, @@ -667,7 +691,7 @@ void acpi_ut_add_reference(union acpi_operand_object *object) /* Increment the reference count */ (void)acpi_ut_update_object_reference(object, REF_INCREMENT); - return_VOID; + return; } /******************************************************************************* @@ -685,7 +709,7 @@ void acpi_ut_add_reference(union acpi_operand_object *object) void acpi_ut_remove_reference(union acpi_operand_object *object) { - ACPI_FUNCTION_TRACE_PTR(ut_remove_reference, object); + ACPI_FUNCTION_NAME(ut_remove_reference); /* * Allow a NULL pointer to be passed in, just ignore it. This saves @@ -694,13 +718,13 @@ void acpi_ut_remove_reference(union acpi_operand_object *object) */ if (!object || (ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_NAMED)) { - return_VOID; + return; } /* Ensure that we have a valid object */ if (!acpi_ut_valid_internal_object(object)) { - return_VOID; + return; } ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, @@ -713,5 +737,5 @@ void acpi_ut_remove_reference(union acpi_operand_object *object) * of all subobjects!) */ (void)acpi_ut_update_object_reference(object, REF_DECREMENT); - return_VOID; + return; } diff --git a/drivers/acpi/acpica/uteval.c b/drivers/acpi/acpica/uteval.c index a9c65fbea5f45d6313218acbd341aba25196d1b8..c3f3a7e7bdc7fd6bc51ba43b1d8ff8e3c6d6eb76 100644 --- a/drivers/acpi/acpica/uteval.c +++ b/drivers/acpi/acpica/uteval.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -68,7 +68,7 @@ ACPI_MODULE_NAME("uteval") ******************************************************************************/ acpi_status -acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node, +acpi_ut_evaluate_object(struct acpi_namespace_node * prefix_node, char *path, u32 expected_return_btypes, union acpi_operand_object **return_desc) diff --git a/drivers/acpi/acpica/utexcep.c b/drivers/acpi/acpica/utexcep.c index 23b98945f6b7e0c568fd166634799dba003a985b..a0ab7c02e87ca8b35581a27aecdfc37fa5b20b63 100644 --- a/drivers/acpi/acpica/utexcep.c +++ b/drivers/acpi/acpica/utexcep.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c index ed1893155f8b855172eb43e930ac144727cca697..ffecf4b4f0ddad70f243811cd7697b931f7e9142 100644 --- a/drivers/acpi/acpica/utglobal.c +++ b/drivers/acpi/acpica/utglobal.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -293,11 +293,11 @@ acpi_status acpi_ut_init_globals(void) /* GPE support */ + acpi_gbl_all_gpes_initialized = FALSE; acpi_gbl_gpe_xrupt_list_head = NULL; acpi_gbl_gpe_fadt_blocks[0] = NULL; acpi_gbl_gpe_fadt_blocks[1] = NULL; acpi_current_gpe_count = 0; - acpi_gbl_all_gpes_initialized = FALSE; acpi_gbl_global_event_handler = NULL; @@ -357,17 +357,24 @@ acpi_status acpi_ut_init_globals(void) acpi_gbl_root_node_struct.peer = NULL; acpi_gbl_root_node_struct.object = NULL; +#ifdef ACPI_DISASSEMBLER + acpi_gbl_external_list = NULL; +#endif + #ifdef ACPI_DEBUG_OUTPUT acpi_gbl_lowest_stack_pointer = ACPI_CAST_PTR(acpi_size, ACPI_SIZE_MAX); #endif #ifdef ACPI_DBG_TRACK_ALLOCATIONS acpi_gbl_display_final_mem_stats = FALSE; + acpi_gbl_disable_mem_tracking = FALSE; #endif return_ACPI_STATUS(AE_OK); } +/* Public globals */ + ACPI_EXPORT_SYMBOL(acpi_gbl_FADT) ACPI_EXPORT_SYMBOL(acpi_dbg_level) ACPI_EXPORT_SYMBOL(acpi_dbg_layer) diff --git a/drivers/acpi/acpica/utids.c b/drivers/acpi/acpica/utids.c index 774c3aefbf5df8d4fd58b2c17ebbc17222e2564c..43a170a74a6139ae3aa10ae1120b27f773103085 100644 --- a/drivers/acpi/acpica/utids.c +++ b/drivers/acpi/acpica/utids.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utinit.c b/drivers/acpi/acpica/utinit.c index 246798e4c938d4f537d2f17290366a5b99f045a7..c5d1ac44c07dd2bf87bfdeec43fc719cce2a3c78 100644 --- a/drivers/acpi/acpica/utinit.c +++ b/drivers/acpi/acpica/utinit.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utlock.c b/drivers/acpi/acpica/utlock.c index b1eb7f17e11065a608be7e8095bf24b9e1d17fb7..5c26ad420344437dbc9b3294531ff82d91a2eec0 100644 --- a/drivers/acpi/acpica/utlock.c +++ b/drivers/acpi/acpica/utlock.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -66,11 +66,11 @@ acpi_status acpi_ut_create_rw_lock(struct acpi_rw_lock *lock) lock->num_readers = 0; status = acpi_os_create_mutex(&lock->reader_mutex); if (ACPI_FAILURE(status)) { - return status; + return (status); } status = acpi_os_create_mutex(&lock->writer_mutex); - return status; + return (status); } void acpi_ut_delete_rw_lock(struct acpi_rw_lock *lock) @@ -108,7 +108,7 @@ acpi_status acpi_ut_acquire_read_lock(struct acpi_rw_lock *lock) status = acpi_os_acquire_mutex(lock->reader_mutex, ACPI_WAIT_FOREVER); if (ACPI_FAILURE(status)) { - return status; + return (status); } /* Acquire the write lock only for the first reader */ @@ -121,7 +121,7 @@ acpi_status acpi_ut_acquire_read_lock(struct acpi_rw_lock *lock) } acpi_os_release_mutex(lock->reader_mutex); - return status; + return (status); } acpi_status acpi_ut_release_read_lock(struct acpi_rw_lock *lock) @@ -130,7 +130,7 @@ acpi_status acpi_ut_release_read_lock(struct acpi_rw_lock *lock) status = acpi_os_acquire_mutex(lock->reader_mutex, ACPI_WAIT_FOREVER); if (ACPI_FAILURE(status)) { - return status; + return (status); } /* Release the write lock only for the very last reader */ @@ -141,7 +141,7 @@ acpi_status acpi_ut_release_read_lock(struct acpi_rw_lock *lock) } acpi_os_release_mutex(lock->reader_mutex); - return status; + return (status); } /******************************************************************************* @@ -165,7 +165,7 @@ acpi_status acpi_ut_acquire_write_lock(struct acpi_rw_lock *lock) acpi_status status; status = acpi_os_acquire_mutex(lock->writer_mutex, ACPI_WAIT_FOREVER); - return status; + return (status); } void acpi_ut_release_write_lock(struct acpi_rw_lock *lock) diff --git a/drivers/acpi/acpica/utmath.c b/drivers/acpi/acpica/utmath.c index 49563674833a9a1d7c396b65b3c7d6f71e390b9f..909fe66e19349b207bf48527e41c0e07f3918cbb 100644 --- a/drivers/acpi/acpica/utmath.c +++ b/drivers/acpi/acpica/utmath.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utmisc.c b/drivers/acpi/acpica/utmisc.c index 9286a69eb9aae34960a6c8ff0e62698ece07d7e6..785fdd07ae5673db012d27b1519dce75e85c3827 100644 --- a/drivers/acpi/acpica/utmisc.c +++ b/drivers/acpi/acpica/utmisc.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -48,36 +48,6 @@ #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME("utmisc") -#if defined ACPI_ASL_COMPILER || defined ACPI_EXEC_APP -/******************************************************************************* - * - * FUNCTION: ut_convert_backslashes - * - * PARAMETERS: pathname - File pathname string to be converted - * - * RETURN: Modifies the input Pathname - * - * DESCRIPTION: Convert all backslashes (0x5C) to forward slashes (0x2F) within - * the entire input file pathname string. - * - ******************************************************************************/ -void ut_convert_backslashes(char *pathname) -{ - - if (!pathname) { - return; - } - - while (*pathname) { - if (*pathname == '\\') { - *pathname = '/'; - } - - pathname++; - } -} -#endif - /******************************************************************************* * * FUNCTION: acpi_ut_is_pci_root_bridge @@ -89,7 +59,6 @@ void ut_convert_backslashes(char *pathname) * DESCRIPTION: Determine if the input ID is a PCI Root Bridge ID. * ******************************************************************************/ - u8 acpi_ut_is_pci_root_bridge(char *id) { @@ -134,362 +103,6 @@ u8 acpi_ut_is_aml_table(struct acpi_table_header *table) return (FALSE); } -/******************************************************************************* - * - * FUNCTION: acpi_ut_allocate_owner_id - * - * PARAMETERS: owner_id - Where the new owner ID is returned - * - * RETURN: Status - * - * DESCRIPTION: Allocate a table or method owner ID. The owner ID is used to - * track objects created by the table or method, to be deleted - * when the method exits or the table is unloaded. - * - ******************************************************************************/ - -acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id) -{ - u32 i; - u32 j; - u32 k; - acpi_status status; - - ACPI_FUNCTION_TRACE(ut_allocate_owner_id); - - /* Guard against multiple allocations of ID to the same location */ - - if (*owner_id) { - ACPI_ERROR((AE_INFO, "Owner ID [0x%2.2X] already exists", - *owner_id)); - return_ACPI_STATUS(AE_ALREADY_EXISTS); - } - - /* Mutex for the global ID mask */ - - status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* - * Find a free owner ID, cycle through all possible IDs on repeated - * allocations. (ACPI_NUM_OWNERID_MASKS + 1) because first index may have - * to be scanned twice. - */ - for (i = 0, j = acpi_gbl_last_owner_id_index; - i < (ACPI_NUM_OWNERID_MASKS + 1); i++, j++) { - if (j >= ACPI_NUM_OWNERID_MASKS) { - j = 0; /* Wraparound to start of mask array */ - } - - for (k = acpi_gbl_next_owner_id_offset; k < 32; k++) { - if (acpi_gbl_owner_id_mask[j] == ACPI_UINT32_MAX) { - - /* There are no free IDs in this mask */ - - break; - } - - if (!(acpi_gbl_owner_id_mask[j] & (1 << k))) { - /* - * Found a free ID. The actual ID is the bit index plus one, - * making zero an invalid Owner ID. Save this as the last ID - * allocated and update the global ID mask. - */ - acpi_gbl_owner_id_mask[j] |= (1 << k); - - acpi_gbl_last_owner_id_index = (u8)j; - acpi_gbl_next_owner_id_offset = (u8)(k + 1); - - /* - * Construct encoded ID from the index and bit position - * - * Note: Last [j].k (bit 255) is never used and is marked - * permanently allocated (prevents +1 overflow) - */ - *owner_id = - (acpi_owner_id) ((k + 1) + ACPI_MUL_32(j)); - - ACPI_DEBUG_PRINT((ACPI_DB_VALUES, - "Allocated OwnerId: %2.2X\n", - (unsigned int)*owner_id)); - goto exit; - } - } - - acpi_gbl_next_owner_id_offset = 0; - } - - /* - * All owner_ids have been allocated. This typically should - * not happen since the IDs are reused after deallocation. The IDs are - * allocated upon table load (one per table) and method execution, and - * they are released when a table is unloaded or a method completes - * execution. - * - * If this error happens, there may be very deep nesting of invoked control - * methods, or there may be a bug where the IDs are not released. - */ - status = AE_OWNER_ID_LIMIT; - ACPI_ERROR((AE_INFO, - "Could not allocate new OwnerId (255 max), AE_OWNER_ID_LIMIT")); - - exit: - (void)acpi_ut_release_mutex(ACPI_MTX_CACHES); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_release_owner_id - * - * PARAMETERS: owner_id_ptr - Pointer to a previously allocated owner_ID - * - * RETURN: None. No error is returned because we are either exiting a - * control method or unloading a table. Either way, we would - * ignore any error anyway. - * - * DESCRIPTION: Release a table or method owner ID. Valid IDs are 1 - 255 - * - ******************************************************************************/ - -void acpi_ut_release_owner_id(acpi_owner_id * owner_id_ptr) -{ - acpi_owner_id owner_id = *owner_id_ptr; - acpi_status status; - u32 index; - u32 bit; - - ACPI_FUNCTION_TRACE_U32(ut_release_owner_id, owner_id); - - /* Always clear the input owner_id (zero is an invalid ID) */ - - *owner_id_ptr = 0; - - /* Zero is not a valid owner_ID */ - - if (owner_id == 0) { - ACPI_ERROR((AE_INFO, "Invalid OwnerId: 0x%2.2X", owner_id)); - return_VOID; - } - - /* Mutex for the global ID mask */ - - status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES); - if (ACPI_FAILURE(status)) { - return_VOID; - } - - /* Normalize the ID to zero */ - - owner_id--; - - /* Decode ID to index/offset pair */ - - index = ACPI_DIV_32(owner_id); - bit = 1 << ACPI_MOD_32(owner_id); - - /* Free the owner ID only if it is valid */ - - if (acpi_gbl_owner_id_mask[index] & bit) { - acpi_gbl_owner_id_mask[index] ^= bit; - } else { - ACPI_ERROR((AE_INFO, - "Release of non-allocated OwnerId: 0x%2.2X", - owner_id + 1)); - } - - (void)acpi_ut_release_mutex(ACPI_MTX_CACHES); - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_strupr (strupr) - * - * PARAMETERS: src_string - The source string to convert - * - * RETURN: None - * - * DESCRIPTION: Convert string to uppercase - * - * NOTE: This is not a POSIX function, so it appears here, not in utclib.c - * - ******************************************************************************/ - -void acpi_ut_strupr(char *src_string) -{ - char *string; - - ACPI_FUNCTION_ENTRY(); - - if (!src_string) { - return; - } - - /* Walk entire string, uppercasing the letters */ - - for (string = src_string; *string; string++) { - *string = (char)ACPI_TOUPPER(*string); - } - - return; -} - -#ifdef ACPI_ASL_COMPILER -/******************************************************************************* - * - * FUNCTION: acpi_ut_strlwr (strlwr) - * - * PARAMETERS: src_string - The source string to convert - * - * RETURN: None - * - * DESCRIPTION: Convert string to lowercase - * - * NOTE: This is not a POSIX function, so it appears here, not in utclib.c - * - ******************************************************************************/ - -void acpi_ut_strlwr(char *src_string) -{ - char *string; - - ACPI_FUNCTION_ENTRY(); - - if (!src_string) { - return; - } - - /* Walk entire string, lowercasing the letters */ - - for (string = src_string; *string; string++) { - *string = (char)ACPI_TOLOWER(*string); - } - - return; -} - -/****************************************************************************** - * - * FUNCTION: acpi_ut_stricmp - * - * PARAMETERS: string1 - first string to compare - * string2 - second string to compare - * - * RETURN: int that signifies string relationship. Zero means strings - * are equal. - * - * DESCRIPTION: Implementation of the non-ANSI stricmp function (compare - * strings with no case sensitivity) - * - ******************************************************************************/ - -int acpi_ut_stricmp(char *string1, char *string2) -{ - int c1; - int c2; - - do { - c1 = tolower((int)*string1); - c2 = tolower((int)*string2); - - string1++; - string2++; - } - while ((c1 == c2) && (c1)); - - return (c1 - c2); -} -#endif - -/******************************************************************************* - * - * FUNCTION: acpi_ut_print_string - * - * PARAMETERS: string - Null terminated ASCII string - * max_length - Maximum output length - * - * RETURN: None - * - * DESCRIPTION: Dump an ASCII string with support for ACPI-defined escape - * sequences. - * - ******************************************************************************/ - -void acpi_ut_print_string(char *string, u8 max_length) -{ - u32 i; - - if (!string) { - acpi_os_printf("<\"NULL STRING PTR\">"); - return; - } - - acpi_os_printf("\""); - for (i = 0; string[i] && (i < max_length); i++) { - - /* Escape sequences */ - - switch (string[i]) { - case 0x07: - acpi_os_printf("\\a"); /* BELL */ - break; - - case 0x08: - acpi_os_printf("\\b"); /* BACKSPACE */ - break; - - case 0x0C: - acpi_os_printf("\\f"); /* FORMFEED */ - break; - - case 0x0A: - acpi_os_printf("\\n"); /* LINEFEED */ - break; - - case 0x0D: - acpi_os_printf("\\r"); /* CARRIAGE RETURN */ - break; - - case 0x09: - acpi_os_printf("\\t"); /* HORIZONTAL TAB */ - break; - - case 0x0B: - acpi_os_printf("\\v"); /* VERTICAL TAB */ - break; - - case '\'': /* Single Quote */ - case '\"': /* Double Quote */ - case '\\': /* Backslash */ - acpi_os_printf("\\%c", (int)string[i]); - break; - - default: - - /* Check for printable character or hex escape */ - - if (ACPI_IS_PRINT(string[i])) { - /* This is a normal character */ - - acpi_os_printf("%c", (int)string[i]); - } else { - /* All others will be Hex escapes */ - - acpi_os_printf("\\x%2.2X", (s32) string[i]); - } - break; - } - } - acpi_os_printf("\""); - - if (i == max_length && string[i]) { - acpi_os_printf("..."); - } -} - /******************************************************************************* * * FUNCTION: acpi_ut_dword_byte_swap @@ -559,379 +172,6 @@ void acpi_ut_set_integer_width(u8 revision) } } -#ifdef ACPI_DEBUG_OUTPUT -/******************************************************************************* - * - * FUNCTION: acpi_ut_display_init_pathname - * - * PARAMETERS: type - Object type of the node - * obj_handle - Handle whose pathname will be displayed - * path - Additional path string to be appended. - * (NULL if no extra path) - * - * RETURN: acpi_status - * - * DESCRIPTION: Display full pathname of an object, DEBUG ONLY - * - ******************************************************************************/ - -void -acpi_ut_display_init_pathname(u8 type, - struct acpi_namespace_node *obj_handle, - char *path) -{ - acpi_status status; - struct acpi_buffer buffer; - - ACPI_FUNCTION_ENTRY(); - - /* Only print the path if the appropriate debug level is enabled */ - - if (!(acpi_dbg_level & ACPI_LV_INIT_NAMES)) { - return; - } - - /* Get the full pathname to the node */ - - buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; - status = acpi_ns_handle_to_pathname(obj_handle, &buffer); - if (ACPI_FAILURE(status)) { - return; - } - - /* Print what we're doing */ - - switch (type) { - case ACPI_TYPE_METHOD: - acpi_os_printf("Executing "); - break; - - default: - acpi_os_printf("Initializing "); - break; - } - - /* Print the object type and pathname */ - - acpi_os_printf("%-12s %s", - acpi_ut_get_type_name(type), (char *)buffer.pointer); - - /* Extra path is used to append names like _STA, _INI, etc. */ - - if (path) { - acpi_os_printf(".%s", path); - } - acpi_os_printf("\n"); - - ACPI_FREE(buffer.pointer); -} -#endif - -/******************************************************************************* - * - * FUNCTION: acpi_ut_valid_acpi_char - * - * PARAMETERS: char - The character to be examined - * position - Byte position (0-3) - * - * RETURN: TRUE if the character is valid, FALSE otherwise - * - * DESCRIPTION: Check for a valid ACPI character. Must be one of: - * 1) Upper case alpha - * 2) numeric - * 3) underscore - * - * We allow a '!' as the last character because of the ASF! table - * - ******************************************************************************/ - -u8 acpi_ut_valid_acpi_char(char character, u32 position) -{ - - if (!((character >= 'A' && character <= 'Z') || - (character >= '0' && character <= '9') || (character == '_'))) { - - /* Allow a '!' in the last position */ - - if (character == '!' && position == 3) { - return (TRUE); - } - - return (FALSE); - } - - return (TRUE); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_valid_acpi_name - * - * PARAMETERS: name - The name to be examined - * - * RETURN: TRUE if the name is valid, FALSE otherwise - * - * DESCRIPTION: Check for a valid ACPI name. Each character must be one of: - * 1) Upper case alpha - * 2) numeric - * 3) underscore - * - ******************************************************************************/ - -u8 acpi_ut_valid_acpi_name(u32 name) -{ - u32 i; - - ACPI_FUNCTION_ENTRY(); - - for (i = 0; i < ACPI_NAME_SIZE; i++) { - if (!acpi_ut_valid_acpi_char - ((ACPI_CAST_PTR(char, &name))[i], i)) { - return (FALSE); - } - } - - return (TRUE); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_repair_name - * - * PARAMETERS: name - The ACPI name to be repaired - * - * RETURN: Repaired version of the name - * - * DESCRIPTION: Repair an ACPI name: Change invalid characters to '*' and - * return the new name. NOTE: the Name parameter must reside in - * read/write memory, cannot be a const. - * - * An ACPI Name must consist of valid ACPI characters. We will repair the name - * if necessary because we don't want to abort because of this, but we want - * all namespace names to be printable. A warning message is appropriate. - * - * This issue came up because there are in fact machines that exhibit - * this problem, and we want to be able to enable ACPI support for them, - * even though there are a few bad names. - * - ******************************************************************************/ - -void acpi_ut_repair_name(char *name) -{ - u32 i; - u8 found_bad_char = FALSE; - u32 original_name; - - ACPI_FUNCTION_NAME(ut_repair_name); - - ACPI_MOVE_NAME(&original_name, name); - - /* Check each character in the name */ - - for (i = 0; i < ACPI_NAME_SIZE; i++) { - if (acpi_ut_valid_acpi_char(name[i], i)) { - continue; - } - - /* - * Replace a bad character with something printable, yet technically - * still invalid. This prevents any collisions with existing "good" - * names in the namespace. - */ - name[i] = '*'; - found_bad_char = TRUE; - } - - if (found_bad_char) { - - /* Report warning only if in strict mode or debug mode */ - - if (!acpi_gbl_enable_interpreter_slack) { - ACPI_WARNING((AE_INFO, - "Found bad character(s) in name, repaired: [%4.4s]\n", - name)); - } else { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Found bad character(s) in name, repaired: [%4.4s]\n", - name)); - } - } -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_strtoul64 - * - * PARAMETERS: string - Null terminated string - * base - Radix of the string: 16 or ACPI_ANY_BASE; - * ACPI_ANY_BASE means 'in behalf of to_integer' - * ret_integer - Where the converted integer is returned - * - * RETURN: Status and Converted value - * - * DESCRIPTION: Convert a string into an unsigned value. Performs either a - * 32-bit or 64-bit conversion, depending on the current mode - * of the interpreter. - * NOTE: Does not support Octal strings, not needed. - * - ******************************************************************************/ - -acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer) -{ - u32 this_digit = 0; - u64 return_value = 0; - u64 quotient; - u64 dividend; - u32 to_integer_op = (base == ACPI_ANY_BASE); - u32 mode32 = (acpi_gbl_integer_byte_width == 4); - u8 valid_digits = 0; - u8 sign_of0x = 0; - u8 term = 0; - - ACPI_FUNCTION_TRACE_STR(ut_stroul64, string); - - switch (base) { - case ACPI_ANY_BASE: - case 16: - break; - - default: - /* Invalid Base */ - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - if (!string) { - goto error_exit; - } - - /* Skip over any white space in the buffer */ - - while ((*string) && (ACPI_IS_SPACE(*string) || *string == '\t')) { - string++; - } - - if (to_integer_op) { - /* - * Base equal to ACPI_ANY_BASE means 'ToInteger operation case'. - * We need to determine if it is decimal or hexadecimal. - */ - if ((*string == '0') && (ACPI_TOLOWER(*(string + 1)) == 'x')) { - sign_of0x = 1; - base = 16; - - /* Skip over the leading '0x' */ - string += 2; - } else { - base = 10; - } - } - - /* Any string left? Check that '0x' is not followed by white space. */ - - if (!(*string) || ACPI_IS_SPACE(*string) || *string == '\t') { - if (to_integer_op) { - goto error_exit; - } else { - goto all_done; - } - } - - /* - * Perform a 32-bit or 64-bit conversion, depending upon the current - * execution mode of the interpreter - */ - dividend = (mode32) ? ACPI_UINT32_MAX : ACPI_UINT64_MAX; - - /* Main loop: convert the string to a 32- or 64-bit integer */ - - while (*string) { - if (ACPI_IS_DIGIT(*string)) { - - /* Convert ASCII 0-9 to Decimal value */ - - this_digit = ((u8)*string) - '0'; - } else if (base == 10) { - - /* Digit is out of range; possible in to_integer case only */ - - term = 1; - } else { - this_digit = (u8)ACPI_TOUPPER(*string); - if (ACPI_IS_XDIGIT((char)this_digit)) { - - /* Convert ASCII Hex char to value */ - - this_digit = this_digit - 'A' + 10; - } else { - term = 1; - } - } - - if (term) { - if (to_integer_op) { - goto error_exit; - } else { - break; - } - } else if ((valid_digits == 0) && (this_digit == 0) - && !sign_of0x) { - - /* Skip zeros */ - string++; - continue; - } - - valid_digits++; - - if (sign_of0x - && ((valid_digits > 16) - || ((valid_digits > 8) && mode32))) { - /* - * This is to_integer operation case. - * No any restrictions for string-to-integer conversion, - * see ACPI spec. - */ - goto error_exit; - } - - /* Divide the digit into the correct position */ - - (void)acpi_ut_short_divide((dividend - (u64)this_digit), - base, "ient, NULL); - - if (return_value > quotient) { - if (to_integer_op) { - goto error_exit; - } else { - break; - } - } - - return_value *= base; - return_value += this_digit; - string++; - } - - /* All done, normal exit */ - - all_done: - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Converted value: %8.8X%8.8X\n", - ACPI_FORMAT_UINT64(return_value))); - - *ret_integer = return_value; - return_ACPI_STATUS(AE_OK); - - error_exit: - /* Base was set/validated above */ - - if (base == 10) { - return_ACPI_STATUS(AE_BAD_DECIMAL_CONSTANT); - } else { - return_ACPI_STATUS(AE_BAD_HEX_CONSTANT); - } -} - /******************************************************************************* * * FUNCTION: acpi_ut_create_update_state_and_push @@ -1097,3 +337,71 @@ acpi_ut_walk_package_tree(union acpi_operand_object *source_object, return_ACPI_STATUS(AE_AML_INTERNAL); } + +#ifdef ACPI_DEBUG_OUTPUT +/******************************************************************************* + * + * FUNCTION: acpi_ut_display_init_pathname + * + * PARAMETERS: type - Object type of the node + * obj_handle - Handle whose pathname will be displayed + * path - Additional path string to be appended. + * (NULL if no extra path) + * + * RETURN: acpi_status + * + * DESCRIPTION: Display full pathname of an object, DEBUG ONLY + * + ******************************************************************************/ + +void +acpi_ut_display_init_pathname(u8 type, + struct acpi_namespace_node *obj_handle, + char *path) +{ + acpi_status status; + struct acpi_buffer buffer; + + ACPI_FUNCTION_ENTRY(); + + /* Only print the path if the appropriate debug level is enabled */ + + if (!(acpi_dbg_level & ACPI_LV_INIT_NAMES)) { + return; + } + + /* Get the full pathname to the node */ + + buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; + status = acpi_ns_handle_to_pathname(obj_handle, &buffer); + if (ACPI_FAILURE(status)) { + return; + } + + /* Print what we're doing */ + + switch (type) { + case ACPI_TYPE_METHOD: + acpi_os_printf("Executing "); + break; + + default: + acpi_os_printf("Initializing "); + break; + } + + /* Print the object type and pathname */ + + acpi_os_printf("%-12s %s", + acpi_ut_get_type_name(type), (char *)buffer.pointer); + + /* Extra path is used to append names like _STA, _INI, etc. */ + + if (path) { + acpi_os_printf(".%s", path); + } + acpi_os_printf("\n"); + + ACPI_FREE(buffer.pointer); +} +#endif diff --git a/drivers/acpi/acpica/utmutex.c b/drivers/acpi/acpica/utmutex.c index 5ccf57c0d87eeae8170895a1398f838376b4a55e..22feb99b8e35438767f4f4880332c19d0feb0851 100644 --- a/drivers/acpi/acpica/utmutex.c +++ b/drivers/acpi/acpica/utmutex.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utobject.c b/drivers/acpi/acpica/utobject.c index 5c52ca78f6fa2516de0843fad9893f4a329f6804..1099f5c069f8287fb354f148c9f8d681fcc94e44 100644 --- a/drivers/acpi/acpica/utobject.c +++ b/drivers/acpi/acpica/utobject.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -419,7 +419,7 @@ void acpi_ut_delete_object_desc(union acpi_operand_object *object) { ACPI_FUNCTION_TRACE_PTR(ut_delete_object_desc, object); - /* Object must be a union acpi_operand_object */ + /* Object must be of type union acpi_operand_object */ if (ACPI_GET_DESCRIPTOR_TYPE(object) != ACPI_DESC_TYPE_OPERAND) { ACPI_ERROR((AE_INFO, diff --git a/drivers/acpi/acpica/utosi.c b/drivers/acpi/acpica/utosi.c index 676285d6116d3b55bd57478bac58a8b780c368aa..36a7d361d7cb9b94b961bc6e03ccda6aa2e2ff0f 100644 --- a/drivers/acpi/acpica/utosi.c +++ b/drivers/acpi/acpica/utosi.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utownerid.c b/drivers/acpi/acpica/utownerid.c new file mode 100644 index 0000000000000000000000000000000000000000..835340b26d3742e8a593557d5e8dd9ed424518e5 --- /dev/null +++ b/drivers/acpi/acpica/utownerid.c @@ -0,0 +1,218 @@ +/******************************************************************************* + * + * Module Name: utownerid - Support for Table/Method Owner IDs + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2013, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include "accommon.h" +#include "acnamesp.h" + +#define _COMPONENT ACPI_UTILITIES +ACPI_MODULE_NAME("utownerid") + +/******************************************************************************* + * + * FUNCTION: acpi_ut_allocate_owner_id + * + * PARAMETERS: owner_id - Where the new owner ID is returned + * + * RETURN: Status + * + * DESCRIPTION: Allocate a table or method owner ID. The owner ID is used to + * track objects created by the table or method, to be deleted + * when the method exits or the table is unloaded. + * + ******************************************************************************/ +acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id) +{ + u32 i; + u32 j; + u32 k; + acpi_status status; + + ACPI_FUNCTION_TRACE(ut_allocate_owner_id); + + /* Guard against multiple allocations of ID to the same location */ + + if (*owner_id) { + ACPI_ERROR((AE_INFO, "Owner ID [0x%2.2X] already exists", + *owner_id)); + return_ACPI_STATUS(AE_ALREADY_EXISTS); + } + + /* Mutex for the global ID mask */ + + status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * Find a free owner ID, cycle through all possible IDs on repeated + * allocations. (ACPI_NUM_OWNERID_MASKS + 1) because first index may have + * to be scanned twice. + */ + for (i = 0, j = acpi_gbl_last_owner_id_index; + i < (ACPI_NUM_OWNERID_MASKS + 1); i++, j++) { + if (j >= ACPI_NUM_OWNERID_MASKS) { + j = 0; /* Wraparound to start of mask array */ + } + + for (k = acpi_gbl_next_owner_id_offset; k < 32; k++) { + if (acpi_gbl_owner_id_mask[j] == ACPI_UINT32_MAX) { + + /* There are no free IDs in this mask */ + + break; + } + + if (!(acpi_gbl_owner_id_mask[j] & (1 << k))) { + /* + * Found a free ID. The actual ID is the bit index plus one, + * making zero an invalid Owner ID. Save this as the last ID + * allocated and update the global ID mask. + */ + acpi_gbl_owner_id_mask[j] |= (1 << k); + + acpi_gbl_last_owner_id_index = (u8)j; + acpi_gbl_next_owner_id_offset = (u8)(k + 1); + + /* + * Construct encoded ID from the index and bit position + * + * Note: Last [j].k (bit 255) is never used and is marked + * permanently allocated (prevents +1 overflow) + */ + *owner_id = + (acpi_owner_id) ((k + 1) + ACPI_MUL_32(j)); + + ACPI_DEBUG_PRINT((ACPI_DB_VALUES, + "Allocated OwnerId: %2.2X\n", + (unsigned int)*owner_id)); + goto exit; + } + } + + acpi_gbl_next_owner_id_offset = 0; + } + + /* + * All owner_ids have been allocated. This typically should + * not happen since the IDs are reused after deallocation. The IDs are + * allocated upon table load (one per table) and method execution, and + * they are released when a table is unloaded or a method completes + * execution. + * + * If this error happens, there may be very deep nesting of invoked control + * methods, or there may be a bug where the IDs are not released. + */ + status = AE_OWNER_ID_LIMIT; + ACPI_ERROR((AE_INFO, + "Could not allocate new OwnerId (255 max), AE_OWNER_ID_LIMIT")); + + exit: + (void)acpi_ut_release_mutex(ACPI_MTX_CACHES); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_release_owner_id + * + * PARAMETERS: owner_id_ptr - Pointer to a previously allocated owner_ID + * + * RETURN: None. No error is returned because we are either exiting a + * control method or unloading a table. Either way, we would + * ignore any error anyway. + * + * DESCRIPTION: Release a table or method owner ID. Valid IDs are 1 - 255 + * + ******************************************************************************/ + +void acpi_ut_release_owner_id(acpi_owner_id * owner_id_ptr) +{ + acpi_owner_id owner_id = *owner_id_ptr; + acpi_status status; + u32 index; + u32 bit; + + ACPI_FUNCTION_TRACE_U32(ut_release_owner_id, owner_id); + + /* Always clear the input owner_id (zero is an invalid ID) */ + + *owner_id_ptr = 0; + + /* Zero is not a valid owner_ID */ + + if (owner_id == 0) { + ACPI_ERROR((AE_INFO, "Invalid OwnerId: 0x%2.2X", owner_id)); + return_VOID; + } + + /* Mutex for the global ID mask */ + + status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES); + if (ACPI_FAILURE(status)) { + return_VOID; + } + + /* Normalize the ID to zero */ + + owner_id--; + + /* Decode ID to index/offset pair */ + + index = ACPI_DIV_32(owner_id); + bit = 1 << ACPI_MOD_32(owner_id); + + /* Free the owner ID only if it is valid */ + + if (acpi_gbl_owner_id_mask[index] & bit) { + acpi_gbl_owner_id_mask[index] ^= bit; + } else { + ACPI_ERROR((AE_INFO, + "Release of non-allocated OwnerId: 0x%2.2X", + owner_id + 1)); + } + + (void)acpi_ut_release_mutex(ACPI_MTX_CACHES); + return_VOID; +} diff --git a/drivers/acpi/acpica/utresrc.c b/drivers/acpi/acpica/utresrc.c index e38bef4980bce9c0be6a7741a339144c3548d390..cb7fa491decf6ab7665091aa56ed0b3ec470ed5a 100644 --- a/drivers/acpi/acpica/utresrc.c +++ b/drivers/acpi/acpica/utresrc.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -127,7 +127,9 @@ const char *acpi_gbl_rw_decode[] = { const char *acpi_gbl_shr_decode[] = { "Exclusive", - "Shared" + "Shared", + "ExclusiveAndWake", /* ACPI 5.0 */ + "SharedAndWake" /* ACPI 5.0 */ }; const char *acpi_gbl_siz_decode[] = { @@ -383,26 +385,16 @@ static const u8 acpi_gbl_resource_types[] = { ACPI_VARIABLE_LENGTH /* 0E *serial_bus */ }; -/* - * For the iASL compiler/disassembler, we don't want any error messages - * because the disassembler uses the resource validation code to determine - * if Buffer objects are actually Resource Templates. - */ -#ifdef ACPI_ASL_COMPILER -#define ACPI_RESOURCE_ERROR(plist) -#else -#define ACPI_RESOURCE_ERROR(plist) ACPI_ERROR(plist) -#endif - /******************************************************************************* * * FUNCTION: acpi_ut_walk_aml_resources * - * PARAMETERS: aml - Pointer to the raw AML resource template - * aml_length - Length of the entire template - * user_function - Called once for each descriptor found. If - * NULL, a pointer to the end_tag is returned - * context - Passed to user_function + * PARAMETERS: walk_state - Current walk info + * PARAMETERS: aml - Pointer to the raw AML resource template + * aml_length - Length of the entire template + * user_function - Called once for each descriptor found. If + * NULL, a pointer to the end_tag is returned + * context - Passed to user_function * * RETURN: Status * @@ -412,7 +404,8 @@ static const u8 acpi_gbl_resource_types[] = { ******************************************************************************/ acpi_status -acpi_ut_walk_aml_resources(u8 * aml, +acpi_ut_walk_aml_resources(struct acpi_walk_state *walk_state, + u8 *aml, acpi_size aml_length, acpi_walk_aml_callback user_function, void **context) { @@ -441,7 +434,8 @@ acpi_ut_walk_aml_resources(u8 * aml, /* Validate the Resource Type and Resource Length */ - status = acpi_ut_validate_resource(aml, &resource_index); + status = + acpi_ut_validate_resource(walk_state, aml, &resource_index); if (ACPI_FAILURE(status)) { /* * Exit on failure. Cannot continue because the descriptor length @@ -498,7 +492,8 @@ acpi_ut_walk_aml_resources(u8 * aml, /* Insert an end_tag anyway. acpi_rs_get_list_length always leaves room */ - (void)acpi_ut_validate_resource(end_tag, &resource_index); + (void)acpi_ut_validate_resource(walk_state, end_tag, + &resource_index); status = user_function(end_tag, 2, offset, resource_index, context); if (ACPI_FAILURE(status)) { @@ -513,9 +508,10 @@ acpi_ut_walk_aml_resources(u8 * aml, * * FUNCTION: acpi_ut_validate_resource * - * PARAMETERS: aml - Pointer to the raw AML resource descriptor - * return_index - Where the resource index is returned. NULL - * if the index is not required. + * PARAMETERS: walk_state - Current walk info + * aml - Pointer to the raw AML resource descriptor + * return_index - Where the resource index is returned. NULL + * if the index is not required. * * RETURN: Status, and optionally the Index into the global resource tables * @@ -525,7 +521,9 @@ acpi_ut_walk_aml_resources(u8 * aml, * ******************************************************************************/ -acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index) +acpi_status +acpi_ut_validate_resource(struct acpi_walk_state *walk_state, + void *aml, u8 *return_index) { union aml_resource *aml_resource; u8 resource_type; @@ -627,10 +625,12 @@ acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index) if ((aml_resource->common_serial_bus.type == 0) || (aml_resource->common_serial_bus.type > AML_RESOURCE_MAX_SERIALBUSTYPE)) { - ACPI_RESOURCE_ERROR((AE_INFO, - "Invalid/unsupported SerialBus resource descriptor: BusType 0x%2.2X", - aml_resource->common_serial_bus. - type)); + if (walk_state) { + ACPI_ERROR((AE_INFO, + "Invalid/unsupported SerialBus resource descriptor: BusType 0x%2.2X", + aml_resource->common_serial_bus. + type)); + } return (AE_AML_INVALID_RESOURCE_TYPE); } } @@ -645,18 +645,22 @@ acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index) invalid_resource: - ACPI_RESOURCE_ERROR((AE_INFO, - "Invalid/unsupported resource descriptor: Type 0x%2.2X", - resource_type)); + if (walk_state) { + ACPI_ERROR((AE_INFO, + "Invalid/unsupported resource descriptor: Type 0x%2.2X", + resource_type)); + } return (AE_AML_INVALID_RESOURCE_TYPE); bad_resource_length: - ACPI_RESOURCE_ERROR((AE_INFO, - "Invalid resource descriptor length: Type " - "0x%2.2X, Length 0x%4.4X, MinLength 0x%4.4X", - resource_type, resource_length, - minimum_resource_length)); + if (walk_state) { + ACPI_ERROR((AE_INFO, + "Invalid resource descriptor length: Type " + "0x%2.2X, Length 0x%4.4X, MinLength 0x%4.4X", + resource_type, resource_length, + minimum_resource_length)); + } return (AE_AML_BAD_RESOURCE_LENGTH); } @@ -800,8 +804,7 @@ u32 acpi_ut_get_descriptor_length(void *aml) ******************************************************************************/ acpi_status -acpi_ut_get_resource_end_tag(union acpi_operand_object * obj_desc, - u8 ** end_tag) +acpi_ut_get_resource_end_tag(union acpi_operand_object *obj_desc, u8 **end_tag) { acpi_status status; @@ -816,7 +819,7 @@ acpi_ut_get_resource_end_tag(union acpi_operand_object * obj_desc, /* Validate the template and get a pointer to the end_tag */ - status = acpi_ut_walk_aml_resources(obj_desc->buffer.pointer, + status = acpi_ut_walk_aml_resources(NULL, obj_desc->buffer.pointer, obj_desc->buffer.length, NULL, (void **)end_tag); diff --git a/drivers/acpi/acpica/utstate.c b/drivers/acpi/acpica/utstate.c index cee0473ba8132b3e70fa264403186ca32cc5fbf0..a6b729d4c1dc9c3a3696f8c7ea8fb396c2a8ab7f 100644 --- a/drivers/acpi/acpica/utstate.c +++ b/drivers/acpi/acpica/utstate.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -97,14 +97,13 @@ void acpi_ut_push_generic_state(union acpi_generic_state **list_head, union acpi_generic_state *state) { - ACPI_FUNCTION_TRACE(ut_push_generic_state); + ACPI_FUNCTION_ENTRY(); /* Push the state object onto the front of the list (stack) */ state->common.next = *list_head; *list_head = state; - - return_VOID; + return; } /******************************************************************************* @@ -124,7 +123,7 @@ union acpi_generic_state *acpi_ut_pop_generic_state(union acpi_generic_state { union acpi_generic_state *state; - ACPI_FUNCTION_TRACE(ut_pop_generic_state); + ACPI_FUNCTION_ENTRY(); /* Remove the state object at the head of the list (stack) */ @@ -136,7 +135,7 @@ union acpi_generic_state *acpi_ut_pop_generic_state(union acpi_generic_state *list_head = state->common.next; } - return_PTR(state); + return (state); } /******************************************************************************* @@ -186,13 +185,13 @@ struct acpi_thread_state *acpi_ut_create_thread_state(void) { union acpi_generic_state *state; - ACPI_FUNCTION_TRACE(ut_create_thread_state); + ACPI_FUNCTION_ENTRY(); /* Create the generic state object */ state = acpi_ut_create_generic_state(); if (!state) { - return_PTR(NULL); + return (NULL); } /* Init fields specific to the update struct */ @@ -207,7 +206,7 @@ struct acpi_thread_state *acpi_ut_create_thread_state(void) state->thread.thread_id = (acpi_thread_id) 1; } - return_PTR((struct acpi_thread_state *)state); + return ((struct acpi_thread_state *)state); } /******************************************************************************* @@ -230,13 +229,13 @@ union acpi_generic_state *acpi_ut_create_update_state(union acpi_operand_object { union acpi_generic_state *state; - ACPI_FUNCTION_TRACE_PTR(ut_create_update_state, object); + ACPI_FUNCTION_ENTRY(); /* Create the generic state object */ state = acpi_ut_create_generic_state(); if (!state) { - return_PTR(NULL); + return (NULL); } /* Init fields specific to the update struct */ @@ -244,8 +243,7 @@ union acpi_generic_state *acpi_ut_create_update_state(union acpi_operand_object state->common.descriptor_type = ACPI_DESC_TYPE_STATE_UPDATE; state->update.object = object; state->update.value = action; - - return_PTR(state); + return (state); } /******************************************************************************* @@ -267,13 +265,13 @@ union acpi_generic_state *acpi_ut_create_pkg_state(void *internal_object, { union acpi_generic_state *state; - ACPI_FUNCTION_TRACE_PTR(ut_create_pkg_state, internal_object); + ACPI_FUNCTION_ENTRY(); /* Create the generic state object */ state = acpi_ut_create_generic_state(); if (!state) { - return_PTR(NULL); + return (NULL); } /* Init fields specific to the update struct */ @@ -283,8 +281,7 @@ union acpi_generic_state *acpi_ut_create_pkg_state(void *internal_object, state->pkg.dest_object = external_object; state->pkg.index = index; state->pkg.num_packages = 1; - - return_PTR(state); + return (state); } /******************************************************************************* @@ -304,21 +301,20 @@ union acpi_generic_state *acpi_ut_create_control_state(void) { union acpi_generic_state *state; - ACPI_FUNCTION_TRACE(ut_create_control_state); + ACPI_FUNCTION_ENTRY(); /* Create the generic state object */ state = acpi_ut_create_generic_state(); if (!state) { - return_PTR(NULL); + return (NULL); } /* Init fields specific to the control struct */ state->common.descriptor_type = ACPI_DESC_TYPE_STATE_CONTROL; state->common.state = ACPI_CONTROL_CONDITIONAL_EXECUTING; - - return_PTR(state); + return (state); } /******************************************************************************* @@ -336,12 +332,12 @@ union acpi_generic_state *acpi_ut_create_control_state(void) void acpi_ut_delete_generic_state(union acpi_generic_state *state) { - ACPI_FUNCTION_TRACE(ut_delete_generic_state); + ACPI_FUNCTION_ENTRY(); /* Ignore null state */ if (state) { (void)acpi_os_release_object(acpi_gbl_state_cache, state); } - return_VOID; + return; } diff --git a/drivers/acpi/acpica/utstring.c b/drivers/acpi/acpica/utstring.c new file mode 100644 index 0000000000000000000000000000000000000000..b3e36a81aa4d1360b9280d2edd6d9d5f9e7330dd --- /dev/null +++ b/drivers/acpi/acpica/utstring.c @@ -0,0 +1,574 @@ +/******************************************************************************* + * + * Module Name: utstring - Common functions for strings and characters + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2013, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include "accommon.h" +#include "acnamesp.h" + +#define _COMPONENT ACPI_UTILITIES +ACPI_MODULE_NAME("utstring") + +/* + * Non-ANSI C library functions - strlwr, strupr, stricmp, and a 64-bit + * version of strtoul. + */ +#ifdef ACPI_ASL_COMPILER +/******************************************************************************* + * + * FUNCTION: acpi_ut_strlwr (strlwr) + * + * PARAMETERS: src_string - The source string to convert + * + * RETURN: None + * + * DESCRIPTION: Convert string to lowercase + * + * NOTE: This is not a POSIX function, so it appears here, not in utclib.c + * + ******************************************************************************/ +void acpi_ut_strlwr(char *src_string) +{ + char *string; + + ACPI_FUNCTION_ENTRY(); + + if (!src_string) { + return; + } + + /* Walk entire string, lowercasing the letters */ + + for (string = src_string; *string; string++) { + *string = (char)ACPI_TOLOWER(*string); + } + + return; +} + +/****************************************************************************** + * + * FUNCTION: acpi_ut_stricmp (stricmp) + * + * PARAMETERS: string1 - first string to compare + * string2 - second string to compare + * + * RETURN: int that signifies string relationship. Zero means strings + * are equal. + * + * DESCRIPTION: Implementation of the non-ANSI stricmp function (compare + * strings with no case sensitivity) + * + ******************************************************************************/ + +int acpi_ut_stricmp(char *string1, char *string2) +{ + int c1; + int c2; + + do { + c1 = tolower((int)*string1); + c2 = tolower((int)*string2); + + string1++; + string2++; + } + while ((c1 == c2) && (c1)); + + return (c1 - c2); +} +#endif + +/******************************************************************************* + * + * FUNCTION: acpi_ut_strupr (strupr) + * + * PARAMETERS: src_string - The source string to convert + * + * RETURN: None + * + * DESCRIPTION: Convert string to uppercase + * + * NOTE: This is not a POSIX function, so it appears here, not in utclib.c + * + ******************************************************************************/ + +void acpi_ut_strupr(char *src_string) +{ + char *string; + + ACPI_FUNCTION_ENTRY(); + + if (!src_string) { + return; + } + + /* Walk entire string, uppercasing the letters */ + + for (string = src_string; *string; string++) { + *string = (char)ACPI_TOUPPER(*string); + } + + return; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_strtoul64 + * + * PARAMETERS: string - Null terminated string + * base - Radix of the string: 16 or ACPI_ANY_BASE; + * ACPI_ANY_BASE means 'in behalf of to_integer' + * ret_integer - Where the converted integer is returned + * + * RETURN: Status and Converted value + * + * DESCRIPTION: Convert a string into an unsigned value. Performs either a + * 32-bit or 64-bit conversion, depending on the current mode + * of the interpreter. + * NOTE: Does not support Octal strings, not needed. + * + ******************************************************************************/ + +acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer) +{ + u32 this_digit = 0; + u64 return_value = 0; + u64 quotient; + u64 dividend; + u32 to_integer_op = (base == ACPI_ANY_BASE); + u32 mode32 = (acpi_gbl_integer_byte_width == 4); + u8 valid_digits = 0; + u8 sign_of0x = 0; + u8 term = 0; + + ACPI_FUNCTION_TRACE_STR(ut_stroul64, string); + + switch (base) { + case ACPI_ANY_BASE: + case 16: + break; + + default: + /* Invalid Base */ + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + if (!string) { + goto error_exit; + } + + /* Skip over any white space in the buffer */ + + while ((*string) && (ACPI_IS_SPACE(*string) || *string == '\t')) { + string++; + } + + if (to_integer_op) { + /* + * Base equal to ACPI_ANY_BASE means 'ToInteger operation case'. + * We need to determine if it is decimal or hexadecimal. + */ + if ((*string == '0') && (ACPI_TOLOWER(*(string + 1)) == 'x')) { + sign_of0x = 1; + base = 16; + + /* Skip over the leading '0x' */ + string += 2; + } else { + base = 10; + } + } + + /* Any string left? Check that '0x' is not followed by white space. */ + + if (!(*string) || ACPI_IS_SPACE(*string) || *string == '\t') { + if (to_integer_op) { + goto error_exit; + } else { + goto all_done; + } + } + + /* + * Perform a 32-bit or 64-bit conversion, depending upon the current + * execution mode of the interpreter + */ + dividend = (mode32) ? ACPI_UINT32_MAX : ACPI_UINT64_MAX; + + /* Main loop: convert the string to a 32- or 64-bit integer */ + + while (*string) { + if (ACPI_IS_DIGIT(*string)) { + + /* Convert ASCII 0-9 to Decimal value */ + + this_digit = ((u8)*string) - '0'; + } else if (base == 10) { + + /* Digit is out of range; possible in to_integer case only */ + + term = 1; + } else { + this_digit = (u8)ACPI_TOUPPER(*string); + if (ACPI_IS_XDIGIT((char)this_digit)) { + + /* Convert ASCII Hex char to value */ + + this_digit = this_digit - 'A' + 10; + } else { + term = 1; + } + } + + if (term) { + if (to_integer_op) { + goto error_exit; + } else { + break; + } + } else if ((valid_digits == 0) && (this_digit == 0) + && !sign_of0x) { + + /* Skip zeros */ + string++; + continue; + } + + valid_digits++; + + if (sign_of0x + && ((valid_digits > 16) + || ((valid_digits > 8) && mode32))) { + /* + * This is to_integer operation case. + * No any restrictions for string-to-integer conversion, + * see ACPI spec. + */ + goto error_exit; + } + + /* Divide the digit into the correct position */ + + (void)acpi_ut_short_divide((dividend - (u64)this_digit), + base, "ient, NULL); + + if (return_value > quotient) { + if (to_integer_op) { + goto error_exit; + } else { + break; + } + } + + return_value *= base; + return_value += this_digit; + string++; + } + + /* All done, normal exit */ + + all_done: + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Converted value: %8.8X%8.8X\n", + ACPI_FORMAT_UINT64(return_value))); + + *ret_integer = return_value; + return_ACPI_STATUS(AE_OK); + + error_exit: + /* Base was set/validated above */ + + if (base == 10) { + return_ACPI_STATUS(AE_BAD_DECIMAL_CONSTANT); + } else { + return_ACPI_STATUS(AE_BAD_HEX_CONSTANT); + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_print_string + * + * PARAMETERS: string - Null terminated ASCII string + * max_length - Maximum output length + * + * RETURN: None + * + * DESCRIPTION: Dump an ASCII string with support for ACPI-defined escape + * sequences. + * + ******************************************************************************/ + +void acpi_ut_print_string(char *string, u8 max_length) +{ + u32 i; + + if (!string) { + acpi_os_printf("<\"NULL STRING PTR\">"); + return; + } + + acpi_os_printf("\""); + for (i = 0; string[i] && (i < max_length); i++) { + + /* Escape sequences */ + + switch (string[i]) { + case 0x07: + acpi_os_printf("\\a"); /* BELL */ + break; + + case 0x08: + acpi_os_printf("\\b"); /* BACKSPACE */ + break; + + case 0x0C: + acpi_os_printf("\\f"); /* FORMFEED */ + break; + + case 0x0A: + acpi_os_printf("\\n"); /* LINEFEED */ + break; + + case 0x0D: + acpi_os_printf("\\r"); /* CARRIAGE RETURN */ + break; + + case 0x09: + acpi_os_printf("\\t"); /* HORIZONTAL TAB */ + break; + + case 0x0B: + acpi_os_printf("\\v"); /* VERTICAL TAB */ + break; + + case '\'': /* Single Quote */ + case '\"': /* Double Quote */ + case '\\': /* Backslash */ + acpi_os_printf("\\%c", (int)string[i]); + break; + + default: + + /* Check for printable character or hex escape */ + + if (ACPI_IS_PRINT(string[i])) { + /* This is a normal character */ + + acpi_os_printf("%c", (int)string[i]); + } else { + /* All others will be Hex escapes */ + + acpi_os_printf("\\x%2.2X", (s32) string[i]); + } + break; + } + } + acpi_os_printf("\""); + + if (i == max_length && string[i]) { + acpi_os_printf("..."); + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_valid_acpi_char + * + * PARAMETERS: char - The character to be examined + * position - Byte position (0-3) + * + * RETURN: TRUE if the character is valid, FALSE otherwise + * + * DESCRIPTION: Check for a valid ACPI character. Must be one of: + * 1) Upper case alpha + * 2) numeric + * 3) underscore + * + * We allow a '!' as the last character because of the ASF! table + * + ******************************************************************************/ + +u8 acpi_ut_valid_acpi_char(char character, u32 position) +{ + + if (!((character >= 'A' && character <= 'Z') || + (character >= '0' && character <= '9') || (character == '_'))) { + + /* Allow a '!' in the last position */ + + if (character == '!' && position == 3) { + return (TRUE); + } + + return (FALSE); + } + + return (TRUE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_valid_acpi_name + * + * PARAMETERS: name - The name to be examined + * + * RETURN: TRUE if the name is valid, FALSE otherwise + * + * DESCRIPTION: Check for a valid ACPI name. Each character must be one of: + * 1) Upper case alpha + * 2) numeric + * 3) underscore + * + ******************************************************************************/ + +u8 acpi_ut_valid_acpi_name(u32 name) +{ + u32 i; + + ACPI_FUNCTION_ENTRY(); + + for (i = 0; i < ACPI_NAME_SIZE; i++) { + if (!acpi_ut_valid_acpi_char + ((ACPI_CAST_PTR(char, &name))[i], i)) { + return (FALSE); + } + } + + return (TRUE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_repair_name + * + * PARAMETERS: name - The ACPI name to be repaired + * + * RETURN: Repaired version of the name + * + * DESCRIPTION: Repair an ACPI name: Change invalid characters to '*' and + * return the new name. NOTE: the Name parameter must reside in + * read/write memory, cannot be a const. + * + * An ACPI Name must consist of valid ACPI characters. We will repair the name + * if necessary because we don't want to abort because of this, but we want + * all namespace names to be printable. A warning message is appropriate. + * + * This issue came up because there are in fact machines that exhibit + * this problem, and we want to be able to enable ACPI support for them, + * even though there are a few bad names. + * + ******************************************************************************/ + +void acpi_ut_repair_name(char *name) +{ + u32 i; + u8 found_bad_char = FALSE; + u32 original_name; + + ACPI_FUNCTION_NAME(ut_repair_name); + + ACPI_MOVE_NAME(&original_name, name); + + /* Check each character in the name */ + + for (i = 0; i < ACPI_NAME_SIZE; i++) { + if (acpi_ut_valid_acpi_char(name[i], i)) { + continue; + } + + /* + * Replace a bad character with something printable, yet technically + * still invalid. This prevents any collisions with existing "good" + * names in the namespace. + */ + name[i] = '*'; + found_bad_char = TRUE; + } + + if (found_bad_char) { + + /* Report warning only if in strict mode or debug mode */ + + if (!acpi_gbl_enable_interpreter_slack) { + ACPI_WARNING((AE_INFO, + "Invalid character(s) in name (0x%.8X), repaired: [%4.4s]", + original_name, name)); + } else { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Invalid character(s) in name (0x%.8X), repaired: [%4.4s]", + original_name, name)); + } + } +} + +#if defined ACPI_ASL_COMPILER || defined ACPI_EXEC_APP +/******************************************************************************* + * + * FUNCTION: ut_convert_backslashes + * + * PARAMETERS: pathname - File pathname string to be converted + * + * RETURN: Modifies the input Pathname + * + * DESCRIPTION: Convert all backslashes (0x5C) to forward slashes (0x2F) within + * the entire input file pathname string. + * + ******************************************************************************/ + +void ut_convert_backslashes(char *pathname) +{ + + if (!pathname) { + return; + } + + while (*pathname) { + if (*pathname == '\\') { + *pathname = '/'; + } + + pathname++; + } +} +#endif diff --git a/drivers/acpi/acpica/uttrack.c b/drivers/acpi/acpica/uttrack.c index a424a9e3fea4c9fd15db96d0fabce89bf5f93ee9..62774c7b76a81402633d417277be05c5953239d0 100644 --- a/drivers/acpi/acpica/uttrack.c +++ b/drivers/acpi/acpica/uttrack.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -436,10 +436,10 @@ acpi_ut_remove_allocation(struct acpi_debug_mem_block *allocation, struct acpi_memory_list *mem_list; acpi_status status; - ACPI_FUNCTION_TRACE(ut_remove_allocation); + ACPI_FUNCTION_NAME(ut_remove_allocation); if (acpi_gbl_disable_mem_tracking) { - return_ACPI_STATUS(AE_OK); + return (AE_OK); } mem_list = acpi_gbl_global_list; @@ -450,12 +450,12 @@ acpi_ut_remove_allocation(struct acpi_debug_mem_block *allocation, ACPI_ERROR((module, line, "Empty allocation list, nothing to free!")); - return_ACPI_STATUS(AE_OK); + return (AE_OK); } status = acpi_ut_acquire_mutex(ACPI_MTX_MEMORY); if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + return (status); } /* Unlink */ @@ -470,15 +470,15 @@ acpi_ut_remove_allocation(struct acpi_debug_mem_block *allocation, (allocation->next)->previous = allocation->previous; } + ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Freeing %p, size 0%X\n", + &allocation->user_space, allocation->size)); + /* Mark the segment as deleted */ ACPI_MEMSET(&allocation->user_space, 0xEA, allocation->size); - ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Freeing size 0%X\n", - allocation->size)); - status = acpi_ut_release_mutex(ACPI_MTX_MEMORY); - return_ACPI_STATUS(status); + return (status); } /******************************************************************************* diff --git a/drivers/acpi/acpica/utxface.c b/drivers/acpi/acpica/utxface.c index 390db0ca5e2e2a223d7afeb83e37581e439837e7..48efb446258c4114fc7ec626ac6a144bffad798a 100644 --- a/drivers/acpi/acpica/utxface.c +++ b/drivers/acpi/acpica/utxface.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,11 +44,7 @@ #include #include #include "accommon.h" -#include "acevents.h" -#include "acnamesp.h" #include "acdebug.h" -#include "actables.h" -#include "acinterp.h" #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME("utxface") diff --git a/drivers/acpi/acpica/utxferror.c b/drivers/acpi/acpica/utxferror.c index d4d3826140d8a1be5d13f5c255933ad3ed59473c..976b6c734fce961b44a94773a4e8357b02727735 100644 --- a/drivers/acpi/acpica/utxferror.c +++ b/drivers/acpi/acpica/utxferror.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -297,9 +297,9 @@ ACPI_EXPORT_SYMBOL(acpi_bios_warning) * * PARAMETERS: module_name - Caller's module name (for error output) * line_number - Caller's line number (for error output) - * Pathname - Full pathname to the node + * pathname - Full pathname to the node * node_flags - From Namespace node for the method/object - * Format - Printf format string + additional args + * format - Printf format string + additional args * * RETURN: None * diff --git a/drivers/acpi/acpica/utxfinit.c b/drivers/acpi/acpica/utxfinit.c index 14f523627a5e9cd60624ef17f9fadd8fd2c9cb16..41ebaaf8bb1a4e08601bf58acd9043103f8c64a5 100644 --- a/drivers/acpi/acpica/utxfinit.c +++ b/drivers/acpi/acpica/utxfinit.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utxfmutex.c b/drivers/acpi/acpica/utxfmutex.c index 0a40a851b3548fe71810e9b893fd01a2d5badd71..312299721ba147ca0128517fbbbab407c416240f 100644 --- a/drivers/acpi/acpica/utxfmutex.c +++ b/drivers/acpi/acpica/utxfmutex.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 7efaeaa53b88a5c8db7f9b2f624e65a432b3283a..c5cd5b5513e67a144ac3a7d2b5a76dc9f494bc48 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -1111,7 +1111,7 @@ static int acpi_battery_add(struct acpi_device *device) return result; } -static int acpi_battery_remove(struct acpi_device *device, int type) +static int acpi_battery_remove(struct acpi_device *device) { struct acpi_battery *battery = NULL; diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 1f0d457ecbcf851a1805916f01ea931672146420..01708a16536829e5d8abdb7f34c0f3dc8415f0ba 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -178,276 +178,6 @@ int acpi_bus_get_private_data(acpi_handle handle, void **data) } EXPORT_SYMBOL(acpi_bus_get_private_data); -/* -------------------------------------------------------------------------- - Power Management - -------------------------------------------------------------------------- */ - -static const char *state_string(int state) -{ - switch (state) { - case ACPI_STATE_D0: - return "D0"; - case ACPI_STATE_D1: - return "D1"; - case ACPI_STATE_D2: - return "D2"; - case ACPI_STATE_D3_HOT: - return "D3hot"; - case ACPI_STATE_D3_COLD: - return "D3"; - default: - return "(unknown)"; - } -} - -static int __acpi_bus_get_power(struct acpi_device *device, int *state) -{ - int result = ACPI_STATE_UNKNOWN; - - if (!device || !state) - return -EINVAL; - - if (!device->flags.power_manageable) { - /* TBD: Non-recursive algorithm for walking up hierarchy. */ - *state = device->parent ? - device->parent->power.state : ACPI_STATE_D0; - goto out; - } - - /* - * Get the device's power state either directly (via _PSC) or - * indirectly (via power resources). - */ - if (device->power.flags.explicit_get) { - unsigned long long psc; - acpi_status status = acpi_evaluate_integer(device->handle, - "_PSC", NULL, &psc); - if (ACPI_FAILURE(status)) - return -ENODEV; - - result = psc; - } - /* The test below covers ACPI_STATE_UNKNOWN too. */ - if (result <= ACPI_STATE_D2) { - ; /* Do nothing. */ - } else if (device->power.flags.power_resources) { - int error = acpi_power_get_inferred_state(device, &result); - if (error) - return error; - } else if (result == ACPI_STATE_D3_HOT) { - result = ACPI_STATE_D3; - } - - /* - * 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. - */ - if (device->parent && device->parent->power.state == ACPI_STATE_UNKNOWN - && result == ACPI_STATE_D0) - device->parent->power.state = ACPI_STATE_D0; - - *state = result; - - out: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] power state is %s\n", - device->pnp.bus_id, state_string(*state))); - - return 0; -} - - -/** - * acpi_device_set_power - Set power state of an ACPI device. - * @device: Device to set the power state of. - * @state: New power state to set. - * - * Callers must ensure that the device is power manageable before using this - * function. - */ -int acpi_device_set_power(struct acpi_device *device, int state) -{ - int result = 0; - acpi_status status = AE_OK; - char object_name[5] = { '_', 'P', 'S', '0' + state, '\0' }; - - if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3_COLD)) - return -EINVAL; - - /* Make sure this is a valid target state */ - - if (state == device->power.state) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at %s\n", - state_string(state))); - return 0; - } - - if (!device->power.states[state].flags.valid) { - printk(KERN_WARNING PREFIX "Device does not support %s\n", - state_string(state)); - return -ENODEV; - } - if (device->parent && (state < device->parent->power.state)) { - printk(KERN_WARNING PREFIX - "Cannot set device to a higher-powered" - " state than parent\n"); - return -ENODEV; - } - - /* For D3cold we should execute _PS3, not _PS4. */ - if (state == ACPI_STATE_D3_COLD) - object_name[3] = '3'; - - /* - * Transition Power - * ---------------- - * On transitions to a high-powered state we first apply power (via - * power resources) then evalute _PSx. Conversly for transitions to - * a lower-powered state. - */ - if (state < device->power.state) { - if (device->power.state >= ACPI_STATE_D3_HOT && - state != ACPI_STATE_D0) { - printk(KERN_WARNING PREFIX - "Cannot transition to non-D0 state from D3\n"); - return -ENODEV; - } - if (device->power.flags.power_resources) { - result = acpi_power_transition(device, state); - if (result) - goto end; - } - if (device->power.states[state].flags.explicit_set) { - status = acpi_evaluate_object(device->handle, - object_name, NULL, NULL); - if (ACPI_FAILURE(status)) { - result = -ENODEV; - goto end; - } - } - } else { - if (device->power.states[state].flags.explicit_set) { - status = acpi_evaluate_object(device->handle, - object_name, NULL, NULL); - if (ACPI_FAILURE(status)) { - result = -ENODEV; - goto end; - } - } - if (device->power.flags.power_resources) { - result = acpi_power_transition(device, state); - if (result) - goto end; - } - } - - end: - if (result) - printk(KERN_WARNING PREFIX - "Device [%s] failed to transition to %s\n", - device->pnp.bus_id, state_string(state)); - else { - device->power.state = state; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Device [%s] transitioned to %s\n", - device->pnp.bus_id, state_string(state))); - } - - return result; -} -EXPORT_SYMBOL(acpi_device_set_power); - - -int acpi_bus_set_power(acpi_handle handle, int state) -{ - struct acpi_device *device; - int result; - - result = acpi_bus_get_device(handle, &device); - if (result) - return result; - - if (!device->flags.power_manageable) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Device [%s] is not power manageable\n", - dev_name(&device->dev))); - return -ENODEV; - } - - return acpi_device_set_power(device, state); -} -EXPORT_SYMBOL(acpi_bus_set_power); - - -int acpi_bus_init_power(struct acpi_device *device) -{ - int state; - int result; - - if (!device) - return -EINVAL; - - device->power.state = ACPI_STATE_UNKNOWN; - - result = __acpi_bus_get_power(device, &state); - if (result) - return result; - - if (device->power.flags.power_resources) - result = acpi_power_on_resources(device, state); - - if (!result) - device->power.state = state; - - return result; -} - - -int acpi_bus_update_power(acpi_handle handle, int *state_p) -{ - struct acpi_device *device; - int state; - int result; - - result = acpi_bus_get_device(handle, &device); - if (result) - return result; - - result = __acpi_bus_get_power(device, &state); - if (result) - return result; - - result = acpi_device_set_power(device, state); - if (!result && state_p) - *state_p = state; - - return result; -} -EXPORT_SYMBOL_GPL(acpi_bus_update_power); - - -bool acpi_bus_power_manageable(acpi_handle handle) -{ - struct acpi_device *device; - int result; - - result = acpi_bus_get_device(handle, &device); - return result ? false : device->flags.power_manageable; -} - -EXPORT_SYMBOL(acpi_bus_power_manageable); - -bool acpi_bus_can_wakeup(acpi_handle handle) -{ - struct acpi_device *device; - int result; - - result = acpi_bus_get_device(handle, &device); - return result ? false : device->wakeup.flags.valid; -} - -EXPORT_SYMBOL(acpi_bus_can_wakeup); - static void acpi_print_osc_error(acpi_handle handle, struct acpi_osc_context *context, char *error) { diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index f0d936b65e375c40be1898fbf49b4cb40006ecb9..86c7d5445c38c962614b654a4149eef0ab057869 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -75,7 +75,7 @@ static const struct acpi_device_id button_device_ids[] = { MODULE_DEVICE_TABLE(acpi, button_device_ids); static int acpi_button_add(struct acpi_device *device); -static int acpi_button_remove(struct acpi_device *device, int type); +static int acpi_button_remove(struct acpi_device *device); static void acpi_button_notify(struct acpi_device *device, u32 event); #ifdef CONFIG_PM_SLEEP @@ -433,7 +433,7 @@ static int acpi_button_add(struct acpi_device *device) return error; } -static int acpi_button_remove(struct acpi_device *device, int type) +static int acpi_button_remove(struct acpi_device *device) { struct acpi_button *button = acpi_driver_data(device); diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c index 811910b50b75c2359505140e481e95398040d884..5523ba7d764dff989c108f5262cbc283c95f329f 100644 --- a/drivers/acpi/container.c +++ b/drivers/acpi/container.c @@ -34,46 +34,34 @@ #include #include #include -#include #define PREFIX "ACPI: " -#define ACPI_CONTAINER_DEVICE_NAME "ACPI container device" -#define ACPI_CONTAINER_CLASS "container" - -#define INSTALL_NOTIFY_HANDLER 1 -#define UNINSTALL_NOTIFY_HANDLER 2 - #define _COMPONENT ACPI_CONTAINER_COMPONENT ACPI_MODULE_NAME("container"); -MODULE_AUTHOR("Anil S Keshavamurthy"); -MODULE_DESCRIPTION("ACPI container driver"); -MODULE_LICENSE("GPL"); - -static int acpi_container_add(struct acpi_device *device); -static int acpi_container_remove(struct acpi_device *device, int type); - static const struct acpi_device_id container_device_ids[] = { {"ACPI0004", 0}, {"PNP0A05", 0}, {"PNP0A06", 0}, {"", 0}, }; -MODULE_DEVICE_TABLE(acpi, container_device_ids); -static struct acpi_driver acpi_container_driver = { - .name = "container", - .class = ACPI_CONTAINER_CLASS, +static int container_device_attach(struct acpi_device *device, + const struct acpi_device_id *not_used) +{ + /* + * FIXME: This is necessary, so that acpi_eject_store() doesn't return + * -ENODEV for containers. + */ + return 1; +} + +static struct acpi_scan_handler container_device_handler = { .ids = container_device_ids, - .ops = { - .add = acpi_container_add, - .remove = acpi_container_remove, - }, + .attach = container_device_attach, }; -/*******************************************************************/ - static int is_device_present(acpi_handle handle) { acpi_handle temp; @@ -92,73 +80,6 @@ static int is_device_present(acpi_handle handle) return ((sta & ACPI_STA_DEVICE_PRESENT) == ACPI_STA_DEVICE_PRESENT); } -static bool is_container_device(const char *hid) -{ - const struct acpi_device_id *container_id; - - for (container_id = container_device_ids; - container_id->id[0]; container_id++) { - if (!strcmp((char *)container_id->id, hid)) - return true; - } - - return false; -} - -/*******************************************************************/ -static int acpi_container_add(struct acpi_device *device) -{ - struct acpi_container *container; - - container = kzalloc(sizeof(struct acpi_container), GFP_KERNEL); - if (!container) - return -ENOMEM; - - container->handle = device->handle; - strcpy(acpi_device_name(device), ACPI_CONTAINER_DEVICE_NAME); - strcpy(acpi_device_class(device), ACPI_CONTAINER_CLASS); - device->driver_data = container; - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device <%s> bid <%s>\n", - acpi_device_name(device), acpi_device_bid(device))); - - return 0; -} - -static int acpi_container_remove(struct acpi_device *device, int type) -{ - acpi_status status = AE_OK; - struct acpi_container *pc = NULL; - - pc = acpi_driver_data(device); - kfree(pc); - return status; -} - -static int container_device_add(struct acpi_device **device, acpi_handle handle) -{ - acpi_handle phandle; - struct acpi_device *pdev; - int result; - - - if (acpi_get_parent(handle, &phandle)) { - return -ENODEV; - } - - if (acpi_bus_get_device(phandle, &pdev)) { - return -ENODEV; - } - - if (acpi_bus_add(device, pdev, handle, ACPI_BUS_TYPE_DEVICE)) { - return -ENODEV; - } - - result = acpi_bus_start(*device); - - return result; -} - static void container_notify_cb(acpi_handle handle, u32 type, void *context) { struct acpi_device *device = NULL; @@ -167,6 +88,8 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context) acpi_status status; u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */ + acpi_scan_lock_acquire(); + switch (type) { case ACPI_NOTIFY_BUS_CHECK: /* Fall through */ @@ -182,7 +105,7 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context) /* device exist and this is a remove request */ device->flags.eject_pending = 1; kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); - return; + goto out; } break; } @@ -190,11 +113,16 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context) if (!ACPI_FAILURE(status) || device) break; - result = container_device_add(&device, handle); + result = acpi_bus_scan(handle); if (result) { acpi_handle_warn(handle, "Failed to add container\n"); break; } + result = acpi_bus_get_device(handle, &device); + if (result) { + acpi_handle_warn(handle, "Missing device object\n"); + break; + } kobject_uevent(&device->dev.kobj, KOBJ_ONLINE); ost_code = ACPI_OST_SC_SUCCESS; @@ -204,98 +132,59 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context) if (!acpi_bus_get_device(handle, &device) && device) { device->flags.eject_pending = 1; kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); - return; + goto out; } break; default: /* non-hotplug event; possibly handled by other handler */ - return; + goto out; } /* Inform firmware that the hotplug operation has completed */ (void) acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL); - return; + + out: + acpi_scan_lock_release(); } -static acpi_status -container_walk_namespace_cb(acpi_handle handle, - u32 lvl, void *context, void **rv) +static bool is_container(acpi_handle handle) { - char *hid = NULL; struct acpi_device_info *info; - acpi_status status; - int *action = context; - - status = acpi_get_object_info(handle, &info); - if (ACPI_FAILURE(status)) { - return AE_OK; - } + bool ret = false; - if (info->valid & ACPI_VALID_HID) - hid = info->hardware_id.string; + if (ACPI_FAILURE(acpi_get_object_info(handle, &info))) + return false; - if (hid == NULL) { - goto end; - } - - if (!is_container_device(hid)) - goto end; + if (info->valid & ACPI_VALID_HID) { + const struct acpi_device_id *id; - switch (*action) { - case INSTALL_NOTIFY_HANDLER: - acpi_install_notify_handler(handle, - ACPI_SYSTEM_NOTIFY, - container_notify_cb, NULL); - break; - case UNINSTALL_NOTIFY_HANDLER: - acpi_remove_notify_handler(handle, - ACPI_SYSTEM_NOTIFY, - container_notify_cb); - break; - default: - break; + for (id = container_device_ids; id->id[0]; id++) { + ret = !strcmp((char *)id->id, info->hardware_id.string); + if (ret) + break; + } } - - end: kfree(info); - - return AE_OK; + return ret; } -static int __init acpi_container_init(void) +static acpi_status acpi_container_register_notify_handler(acpi_handle handle, + u32 lvl, void *ctxt, + void **retv) { - int result = 0; - int action = INSTALL_NOTIFY_HANDLER; - - result = acpi_bus_register_driver(&acpi_container_driver); - if (result < 0) { - return (result); - } - - /* register notify handler to every container device */ - acpi_walk_namespace(ACPI_TYPE_DEVICE, - ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, - container_walk_namespace_cb, NULL, &action, NULL); + if (is_container(handle)) + acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, + container_notify_cb, NULL); - return (0); + return AE_OK; } -static void __exit acpi_container_exit(void) +void __init acpi_container_init(void) { - int action = UNINSTALL_NOTIFY_HANDLER; + acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, + acpi_container_register_notify_handler, NULL, + NULL, NULL); - - acpi_walk_namespace(ACPI_TYPE_DEVICE, - ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, - container_walk_namespace_cb, NULL, &action, NULL); - - acpi_bus_unregister_driver(&acpi_container_driver); - - return; + acpi_scan_add_handler(&container_device_handler); } - -module_init(acpi_container_init); -module_exit(acpi_container_exit); diff --git a/drivers/acpi/csrt.c b/drivers/acpi/csrt.c new file mode 100644 index 0000000000000000000000000000000000000000..5c15a91faf0b6fbd0d0e8653ae02d618fc8e6f45 --- /dev/null +++ b/drivers/acpi/csrt.c @@ -0,0 +1,159 @@ +/* + * Support for Core System Resources Table (CSRT) + * + * Copyright (C) 2013, Intel Corporation + * Authors: Mika Westerberg + * Andy Shevchenko + * + * 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. + */ + +#define pr_fmt(fmt) "ACPI: CSRT: " fmt + +#include +#include +#include +#include +#include +#include + +ACPI_MODULE_NAME("CSRT"); + +static int __init acpi_csrt_parse_shared_info(struct platform_device *pdev, + const struct acpi_csrt_group *grp) +{ + const struct acpi_csrt_shared_info *si; + struct resource res[3]; + size_t nres; + int ret; + + memset(res, 0, sizeof(res)); + nres = 0; + + si = (const struct acpi_csrt_shared_info *)&grp[1]; + /* + * The peripherals that are listed on CSRT typically support only + * 32-bit addresses so we only use the low part of MMIO base for + * now. + */ + if (!si->mmio_base_high && si->mmio_base_low) { + /* + * There is no size of the memory resource in shared_info + * so we assume that it is 4k here. + */ + res[nres].start = si->mmio_base_low; + res[nres].end = res[0].start + SZ_4K - 1; + res[nres++].flags = IORESOURCE_MEM; + } + + if (si->gsi_interrupt) { + int irq = acpi_register_gsi(NULL, si->gsi_interrupt, + si->interrupt_mode, + si->interrupt_polarity); + res[nres].start = irq; + res[nres].end = irq; + res[nres++].flags = IORESOURCE_IRQ; + } + + if (si->base_request_line || si->num_handshake_signals) { + /* + * We pass the driver a DMA resource describing the range + * of request lines the device supports. + */ + res[nres].start = si->base_request_line; + res[nres].end = res[nres].start + si->num_handshake_signals - 1; + res[nres++].flags = IORESOURCE_DMA; + } + + ret = platform_device_add_resources(pdev, res, nres); + if (ret) { + if (si->gsi_interrupt) + acpi_unregister_gsi(si->gsi_interrupt); + return ret; + } + + return 0; +} + +static int __init +acpi_csrt_parse_resource_group(const struct acpi_csrt_group *grp) +{ + struct platform_device *pdev; + char vendor[5], name[16]; + int ret, i; + + vendor[0] = grp->vendor_id; + vendor[1] = grp->vendor_id >> 8; + vendor[2] = grp->vendor_id >> 16; + vendor[3] = grp->vendor_id >> 24; + vendor[4] = '\0'; + + if (grp->shared_info_length != sizeof(struct acpi_csrt_shared_info)) + return -ENODEV; + + snprintf(name, sizeof(name), "%s%04X", vendor, grp->device_id); + pdev = platform_device_alloc(name, PLATFORM_DEVID_AUTO); + if (!pdev) + return -ENOMEM; + + /* Add resources based on the shared info */ + ret = acpi_csrt_parse_shared_info(pdev, grp); + if (ret) + goto fail; + + ret = platform_device_add(pdev); + if (ret) + goto fail; + + for (i = 0; i < pdev->num_resources; i++) + dev_dbg(&pdev->dev, "%pR\n", &pdev->resource[i]); + + return 0; + +fail: + platform_device_put(pdev); + return ret; +} + +/* + * CSRT or Core System Resources Table is a proprietary ACPI table + * introduced by Microsoft. This table can contain devices that are not in + * the system DSDT table. In particular DMA controllers might be described + * here. + * + * We present these devices as normal platform devices that don't have ACPI + * IDs or handle. The platform device name will be something like + * ..auto for example: INTL9C06.0.auto. + */ +void __init acpi_csrt_init(void) +{ + struct acpi_csrt_group *grp, *end; + struct acpi_table_csrt *csrt; + acpi_status status; + int ret; + + status = acpi_get_table(ACPI_SIG_CSRT, 0, + (struct acpi_table_header **)&csrt); + if (ACPI_FAILURE(status)) { + if (status != AE_NOT_FOUND) + pr_warn("failed to get the CSRT table\n"); + return; + } + + pr_debug("parsing CSRT table for devices\n"); + + grp = (struct acpi_csrt_group *)(csrt + 1); + end = (struct acpi_csrt_group *)((void *)csrt + csrt->header.length); + + while (grp < end) { + ret = acpi_csrt_parse_resource_group(grp); + if (ret) { + pr_warn("error in parsing resource group: %d\n", ret); + return; + } + + grp = (struct acpi_csrt_group *)((void *)grp + grp->length); + } +} diff --git a/drivers/acpi/custom_method.c b/drivers/acpi/custom_method.c index 5d42c2414ae54c437051ecd65f2b849dd67b61e3..6adfc706a1de4511f1f08de510e15e1e734e2cc7 100644 --- a/drivers/acpi/custom_method.c +++ b/drivers/acpi/custom_method.c @@ -1,5 +1,5 @@ /* - * debugfs.c - ACPI debugfs interface to userspace. + * custom_method.c - debugfs interface for customizing ACPI control method */ #include diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index c6ff606c6d5bb35d51b2bff23588914f99a6ba83..dd314ef9bff144759154cb9e27eb8bc5ade63213 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -30,6 +30,12 @@ #include #include +#include + +#include "internal.h" + +#define _COMPONENT ACPI_POWER_COMPONENT +ACPI_MODULE_NAME("device_pm"); static DEFINE_MUTEX(acpi_pm_notifier_lock); @@ -93,6 +99,293 @@ acpi_status acpi_remove_pm_notifier(struct acpi_device *adev, return status; } +/** + * acpi_power_state_string - String representation of ACPI device power state. + * @state: ACPI device power state to return the string representation of. + */ +const char *acpi_power_state_string(int state) +{ + switch (state) { + case ACPI_STATE_D0: + return "D0"; + case ACPI_STATE_D1: + return "D1"; + case ACPI_STATE_D2: + return "D2"; + case ACPI_STATE_D3_HOT: + return "D3hot"; + case ACPI_STATE_D3_COLD: + return "D3cold"; + default: + return "(unknown)"; + } +} + +/** + * acpi_device_get_power - Get power state of an ACPI device. + * @device: Device to get the power state of. + * @state: Place to store the power state of the device. + * + * This function does not update the device's power.state field, but it may + * update its parent's power.state field (when the parent's power state is + * unknown and the device's power state turns out to be D0). + */ +int acpi_device_get_power(struct acpi_device *device, int *state) +{ + int result = ACPI_STATE_UNKNOWN; + + if (!device || !state) + return -EINVAL; + + if (!device->flags.power_manageable) { + /* TBD: Non-recursive algorithm for walking up hierarchy. */ + *state = device->parent ? + device->parent->power.state : ACPI_STATE_D0; + goto out; + } + + /* + * Get the device's power state either directly (via _PSC) or + * indirectly (via power resources). + */ + if (device->power.flags.explicit_get) { + unsigned long long psc; + acpi_status status = acpi_evaluate_integer(device->handle, + "_PSC", NULL, &psc); + if (ACPI_FAILURE(status)) + return -ENODEV; + + result = psc; + } + /* The test below covers ACPI_STATE_UNKNOWN too. */ + if (result <= ACPI_STATE_D2) { + ; /* Do nothing. */ + } else if (device->power.flags.power_resources) { + int error = acpi_power_get_inferred_state(device, &result); + if (error) + return error; + } else if (result == ACPI_STATE_D3_HOT) { + result = ACPI_STATE_D3; + } + + /* + * 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. + */ + if (device->parent && device->parent->power.state == ACPI_STATE_UNKNOWN + && result == ACPI_STATE_D0) + device->parent->power.state = ACPI_STATE_D0; + + *state = result; + + out: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] power state is %s\n", + device->pnp.bus_id, acpi_power_state_string(*state))); + + return 0; +} + +static int acpi_dev_pm_explicit_set(struct acpi_device *adev, int state) +{ + if (adev->power.states[state].flags.explicit_set) { + char method[5] = { '_', 'P', 'S', '0' + state, '\0' }; + acpi_status status; + + status = acpi_evaluate_object(adev->handle, method, NULL, NULL); + if (ACPI_FAILURE(status)) + return -ENODEV; + } + return 0; +} + +/** + * acpi_device_set_power - Set power state of an ACPI device. + * @device: Device to set the power state of. + * @state: New power state to set. + * + * Callers must ensure that the device is power manageable before using this + * function. + */ +int acpi_device_set_power(struct acpi_device *device, int state) +{ + int result = 0; + bool cut_power = false; + + if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3_COLD)) + return -EINVAL; + + /* Make sure this is a valid target state */ + + if (state == device->power.state) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at %s\n", + acpi_power_state_string(state))); + return 0; + } + + if (!device->power.states[state].flags.valid) { + printk(KERN_WARNING PREFIX "Device does not support %s\n", + acpi_power_state_string(state)); + return -ENODEV; + } + if (device->parent && (state < device->parent->power.state)) { + printk(KERN_WARNING PREFIX + "Cannot set device to a higher-powered" + " state than parent\n"); + return -ENODEV; + } + + /* For D3cold we should first transition into D3hot. */ + if (state == ACPI_STATE_D3_COLD + && device->power.states[ACPI_STATE_D3_COLD].flags.os_accessible) { + state = ACPI_STATE_D3_HOT; + cut_power = true; + } + + if (state < device->power.state && state != ACPI_STATE_D0 + && device->power.state >= ACPI_STATE_D3_HOT) { + printk(KERN_WARNING PREFIX + "Cannot transition to non-D0 state from D3\n"); + return -ENODEV; + } + + /* + * Transition Power + * ---------------- + * In accordance with the ACPI specification first apply power (via + * power resources) and then evalute _PSx. + */ + if (device->power.flags.power_resources) { + result = acpi_power_transition(device, state); + if (result) + goto end; + } + result = acpi_dev_pm_explicit_set(device, state); + if (result) + goto end; + + if (cut_power) { + device->power.state = state; + state = ACPI_STATE_D3_COLD; + result = acpi_power_transition(device, state); + } + + end: + if (result) { + printk(KERN_WARNING PREFIX + "Device [%s] failed to transition to %s\n", + device->pnp.bus_id, + acpi_power_state_string(state)); + } else { + device->power.state = state; + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Device [%s] transitioned to %s\n", + device->pnp.bus_id, + acpi_power_state_string(state))); + } + + return result; +} +EXPORT_SYMBOL(acpi_device_set_power); + +int acpi_bus_set_power(acpi_handle handle, int state) +{ + struct acpi_device *device; + int result; + + result = acpi_bus_get_device(handle, &device); + if (result) + return result; + + if (!device->flags.power_manageable) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Device [%s] is not power manageable\n", + dev_name(&device->dev))); + return -ENODEV; + } + + return acpi_device_set_power(device, state); +} +EXPORT_SYMBOL(acpi_bus_set_power); + +int acpi_bus_init_power(struct acpi_device *device) +{ + int state; + int result; + + if (!device) + return -EINVAL; + + device->power.state = ACPI_STATE_UNKNOWN; + + result = acpi_device_get_power(device, &state); + if (result) + return result; + + if (state < ACPI_STATE_D3_COLD && device->power.flags.power_resources) { + result = acpi_power_on_resources(device, state); + if (result) + return result; + + result = acpi_dev_pm_explicit_set(device, state); + if (result) + return result; + } else if (state == ACPI_STATE_UNKNOWN) { + /* No power resources and missing _PSC? Try to force D0. */ + state = ACPI_STATE_D0; + result = acpi_dev_pm_explicit_set(device, state); + if (result) + return result; + } + device->power.state = state; + return 0; +} + +int acpi_bus_update_power(acpi_handle handle, int *state_p) +{ + struct acpi_device *device; + int state; + int result; + + result = acpi_bus_get_device(handle, &device); + if (result) + return result; + + result = acpi_device_get_power(device, &state); + if (result) + return result; + + if (state == ACPI_STATE_UNKNOWN) + state = ACPI_STATE_D0; + + result = acpi_device_set_power(device, state); + if (!result && state_p) + *state_p = state; + + return result; +} +EXPORT_SYMBOL_GPL(acpi_bus_update_power); + +bool acpi_bus_power_manageable(acpi_handle handle) +{ + struct acpi_device *device; + int result; + + result = acpi_bus_get_device(handle, &device); + return result ? false : device->flags.power_manageable; +} +EXPORT_SYMBOL(acpi_bus_power_manageable); + +bool acpi_bus_can_wakeup(acpi_handle handle) +{ + struct acpi_device *device; + int result; + + result = acpi_bus_get_device(handle, &device); + return result ? false : device->wakeup.flags.valid; +} +EXPORT_SYMBOL(acpi_bus_can_wakeup); + /** * acpi_device_power_state - Get preferred power state of ACPI device. * @dev: Device whose preferred target power state to return. @@ -213,7 +506,7 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in) acpi_handle handle = DEVICE_ACPI_HANDLE(dev); struct acpi_device *adev; - if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) { + if (!handle || acpi_bus_get_device(handle, &adev)) { dev_dbg(dev, "ACPI handle without context in %s!\n", __func__); return -ENODEV; } @@ -290,7 +583,7 @@ int acpi_pm_device_run_wake(struct device *phys_dev, bool enable) return -EINVAL; handle = DEVICE_ACPI_HANDLE(phys_dev); - if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) { + if (!handle || acpi_bus_get_device(handle, &adev)) { dev_dbg(phys_dev, "ACPI handle without context in %s!\n", __func__); return -ENODEV; @@ -304,7 +597,7 @@ static inline void acpi_wakeup_device(acpi_handle handle, u32 event, void *context) {} #endif /* CONFIG_PM_RUNTIME */ - #ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_PM_SLEEP /** * __acpi_device_sleep_wake - Enable or disable device to wake up the system. * @dev: Device to enable/desible to wake up the system. @@ -334,7 +627,7 @@ int acpi_pm_device_sleep_wake(struct device *dev, bool enable) return -EINVAL; handle = DEVICE_ACPI_HANDLE(dev); - if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) { + if (!handle || acpi_bus_get_device(handle, &adev)) { dev_dbg(dev, "ACPI handle without context in %s!\n", __func__); return -ENODEV; } @@ -353,7 +646,7 @@ int acpi_pm_device_sleep_wake(struct device *dev, bool enable) * acpi_dev_pm_get_node - Get ACPI device node for the given physical device. * @dev: Device to get the ACPI node for. */ -static struct acpi_device *acpi_dev_pm_get_node(struct device *dev) +struct acpi_device *acpi_dev_pm_get_node(struct device *dev) { acpi_handle handle = DEVICE_ACPI_HANDLE(dev); struct acpi_device *adev; @@ -665,3 +958,59 @@ void acpi_dev_pm_detach(struct device *dev, bool power_off) } } EXPORT_SYMBOL_GPL(acpi_dev_pm_detach); + +/** + * acpi_dev_pm_add_dependent - Add physical device depending for PM. + * @handle: Handle of ACPI device node. + * @depdev: Device depending on that node for PM. + */ +void acpi_dev_pm_add_dependent(acpi_handle handle, struct device *depdev) +{ + struct acpi_device_physical_node *dep; + struct acpi_device *adev; + + if (!depdev || acpi_bus_get_device(handle, &adev)) + return; + + mutex_lock(&adev->physical_node_lock); + + list_for_each_entry(dep, &adev->power_dependent, node) + if (dep->dev == depdev) + goto out; + + dep = kzalloc(sizeof(*dep), GFP_KERNEL); + if (dep) { + dep->dev = depdev; + list_add_tail(&dep->node, &adev->power_dependent); + } + + out: + mutex_unlock(&adev->physical_node_lock); +} +EXPORT_SYMBOL_GPL(acpi_dev_pm_add_dependent); + +/** + * acpi_dev_pm_remove_dependent - Remove physical device depending for PM. + * @handle: Handle of ACPI device node. + * @depdev: Device depending on that node for PM. + */ +void acpi_dev_pm_remove_dependent(acpi_handle handle, struct device *depdev) +{ + struct acpi_device_physical_node *dep; + struct acpi_device *adev; + + if (!depdev || acpi_bus_get_device(handle, &adev)) + return; + + mutex_lock(&adev->physical_node_lock); + + list_for_each_entry(dep, &adev->power_dependent, node) + if (dep->dev == depdev) { + list_del(&dep->node); + kfree(dep); + break; + } + + mutex_unlock(&adev->physical_node_lock); +} +EXPORT_SYMBOL_GPL(acpi_dev_pm_remove_dependent); diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index f32bd47b35e0655e438381865eb05e801715c15c..4fdea381ef21e07017a87b94ae16ce0f8860fb75 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -310,8 +310,6 @@ static int dock_present(struct dock_station *ds) static struct acpi_device * dock_create_acpi_device(acpi_handle handle) { struct acpi_device *device; - struct acpi_device *parent_device; - acpi_handle parent; int ret; if (acpi_bus_get_device(handle, &device)) { @@ -319,16 +317,11 @@ static struct acpi_device * dock_create_acpi_device(acpi_handle handle) * no device created for this object, * so we should create one. */ - acpi_get_parent(handle, &parent); - if (acpi_bus_get_device(parent, &parent_device)) - parent_device = NULL; - - ret = acpi_bus_add(&device, parent_device, handle, - ACPI_BUS_TYPE_DEVICE); - if (ret) { + ret = acpi_bus_scan(handle); + if (ret) pr_debug("error adding bus, %x\n", -ret); - return NULL; - } + + acpi_bus_get_device(handle, &device); } return device; } @@ -343,13 +336,9 @@ static struct acpi_device * dock_create_acpi_device(acpi_handle handle) static void dock_remove_acpi_device(acpi_handle handle) { struct acpi_device *device; - int ret; - if (!acpi_bus_get_device(handle, &device)) { - ret = acpi_bus_trim(device, 1); - if (ret) - pr_debug("error removing bus, %x\n", -ret); - } + if (!acpi_bus_get_device(handle, &device)) + acpi_bus_trim(device); } /** @@ -755,7 +744,9 @@ static void acpi_dock_deferred_cb(void *context) { struct dock_data *data = context; + acpi_scan_lock_acquire(); dock_notify(data->handle, data->event, data->ds); + acpi_scan_lock_release(); kfree(data); } @@ -768,20 +759,31 @@ static int acpi_dock_notifier_call(struct notifier_block *this, if (event != ACPI_NOTIFY_BUS_CHECK && event != ACPI_NOTIFY_DEVICE_CHECK && event != ACPI_NOTIFY_EJECT_REQUEST) return 0; + + acpi_scan_lock_acquire(); + list_for_each_entry(dock_station, &dock_stations, sibling) { if (dock_station->handle == handle) { struct dock_data *dd; + acpi_status status; dd = kmalloc(sizeof(*dd), GFP_KERNEL); if (!dd) - return 0; + break; + dd->handle = handle; dd->event = event; dd->ds = dock_station; - acpi_os_hotplug_execute(acpi_dock_deferred_cb, dd); - return 0 ; + status = acpi_os_hotplug_execute(acpi_dock_deferred_cb, + dd); + if (ACPI_FAILURE(status)) + kfree(dd); + + break; } } + + acpi_scan_lock_release(); return 0; } @@ -836,7 +838,7 @@ static ssize_t show_docked(struct device *dev, struct dock_station *dock_station = dev->platform_data; - if (ACPI_SUCCESS(acpi_bus_get_device(dock_station->handle, &tmp))) + if (!acpi_bus_get_device(dock_station->handle, &tmp)) return snprintf(buf, PAGE_SIZE, "1\n"); return snprintf(buf, PAGE_SIZE, "0\n"); } diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 354007d490d1268a6e97cee38ba48fd36c1922f7..d45b2871d33b12fa2453f4f91da1a1d55bf19edc 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -852,7 +852,7 @@ static int acpi_ec_add(struct acpi_device *device) return ret; } -static int acpi_ec_remove(struct acpi_device *device, int type) +static int acpi_ec_remove(struct acpi_device *device) { struct acpi_ec *ec; struct acpi_ec_query_handler *handler, *tmp; diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index 3bd6a54702d683bbca8bcee056293eb938f7d71b..f815da82c765299a42300ae837fd574bedb8e429 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -45,7 +45,7 @@ MODULE_DESCRIPTION("ACPI Fan Driver"); MODULE_LICENSE("GPL"); static int acpi_fan_add(struct acpi_device *device); -static int acpi_fan_remove(struct acpi_device *device, int type); +static int acpi_fan_remove(struct acpi_device *device); static const struct acpi_device_id fan_device_ids[] = { {"PNP0C0B", 0}, @@ -172,7 +172,7 @@ static int acpi_fan_add(struct acpi_device *device) return result; } -static int acpi_fan_remove(struct acpi_device *device, int type) +static int acpi_fan_remove(struct acpi_device *device) { struct thermal_cooling_device *cdev = acpi_driver_data(device); diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 35da18113216c367eae553371e9164a726a70f44..ef6f155469b58ed370aa9d1232d5c2e6bb14c29a 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -68,6 +68,9 @@ static struct acpi_bus_type *acpi_get_bus_type(struct bus_type *type) { struct acpi_bus_type *tmp, *ret = NULL; + if (!type) + return NULL; + down_read(&bus_type_sem); list_for_each_entry(tmp, &bus_type_list, list) { if (tmp->bus == type) { @@ -95,40 +98,31 @@ static int acpi_find_bridge_device(struct device *dev, acpi_handle * handle) return ret; } -/* Get device's handler per its address under its parent */ -struct acpi_find_child { - acpi_handle handle; - u64 address; -}; - -static acpi_status -do_acpi_find_child(acpi_handle handle, u32 lvl, void *context, void **rv) +static acpi_status do_acpi_find_child(acpi_handle handle, u32 lvl_not_used, + void *addr_p, void **ret_p) { + unsigned long long addr; acpi_status status; - struct acpi_device_info *info; - struct acpi_find_child *find = context; - - status = acpi_get_object_info(handle, &info); - if (ACPI_SUCCESS(status)) { - if ((info->address == find->address) - && (info->valid & ACPI_VALID_ADR)) - find->handle = handle; - kfree(info); + + status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &addr); + if (ACPI_SUCCESS(status) && addr == *((u64 *)addr_p)) { + *ret_p = handle; + return AE_CTRL_TERMINATE; } return AE_OK; } acpi_handle acpi_get_child(acpi_handle parent, u64 address) { - struct acpi_find_child find = { NULL, address }; + void *ret = NULL; if (!parent) return NULL; - acpi_walk_namespace(ACPI_TYPE_DEVICE, parent, - 1, do_acpi_find_child, NULL, &find, NULL); - return find.handle; -} + acpi_walk_namespace(ACPI_TYPE_DEVICE, parent, 1, NULL, + do_acpi_find_child, &address, &ret); + return (acpi_handle)ret; +} EXPORT_SYMBOL(acpi_get_child); static int acpi_bind_one(struct device *dev, acpi_handle handle) @@ -269,28 +263,39 @@ static int acpi_platform_notify(struct device *dev) { struct acpi_bus_type *type; acpi_handle handle; - int ret = -EINVAL; + int ret; ret = acpi_bind_one(dev, NULL); - if (!ret) - goto out; - - if (!dev->bus || !dev->parent) { + if (ret && (!dev->bus || !dev->parent)) { /* bridge devices genernally haven't bus or parent */ ret = acpi_find_bridge_device(dev, &handle); - goto end; + if (!ret) { + ret = acpi_bind_one(dev, handle); + if (ret) + goto out; + } } + type = acpi_get_bus_type(dev->bus); - if (!type) { - DBG("No ACPI bus support for %s\n", dev_name(dev)); - ret = -EINVAL; - goto end; + if (ret) { + if (!type || !type->find_device) { + DBG("No ACPI bus support for %s\n", dev_name(dev)); + ret = -EINVAL; + goto out; + } + + ret = type->find_device(dev, &handle); + if (ret) { + DBG("Unable to get handle for %s\n", dev_name(dev)); + goto out; + } + ret = acpi_bind_one(dev, handle); + if (ret) + goto out; } - if ((ret = type->find_device(dev, &handle)) != 0) - DBG("Can't get handler for %s\n", dev_name(dev)); - end: - if (!ret) - acpi_bind_one(dev, handle); + + if (type && type->setup) + type->setup(dev); out: #if ACPI_GLUE_DEBUG @@ -309,6 +314,12 @@ static int acpi_platform_notify(struct device *dev) static int acpi_platform_notify_remove(struct device *dev) { + struct acpi_bus_type *type; + + type = acpi_get_bus_type(dev->bus); + if (type && type->cleanup) + type->cleanup(dev); + acpi_unbind_one(dev); return 0; } diff --git a/drivers/acpi/hed.c b/drivers/acpi/hed.c index a0cc796932f7c6d41eb9fbdf8422031d84f2e210..13b1d39d7cdf57c463534c3a29cfd797e22abfe0 100644 --- a/drivers/acpi/hed.c +++ b/drivers/acpi/hed.c @@ -70,7 +70,7 @@ static int acpi_hed_add(struct acpi_device *device) return 0; } -static int acpi_hed_remove(struct acpi_device *device, int type) +static int acpi_hed_remove(struct acpi_device *device) { hed_handle = NULL; return 0; diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 3c407cdc1ec1ce95acd5b6ce071e41f12d2344d2..79092328cf064b237c090690c29b64ec1a733063 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -25,7 +25,16 @@ int init_acpi_device_notify(void); int acpi_scan_init(void); +void acpi_pci_root_init(void); +void acpi_pci_link_init(void); +void acpi_platform_init(void); int acpi_sysfs_init(void); +void acpi_csrt_init(void); +#ifdef CONFIG_ACPI_CONTAINER +void acpi_container_init(void); +#else +static inline void acpi_container_init(void) {} +#endif #ifdef CONFIG_DEBUG_FS extern struct dentry *acpi_debugfs_dir; @@ -34,16 +43,34 @@ int acpi_debugfs_init(void); static inline void acpi_debugfs_init(void) { return; } #endif +/* -------------------------------------------------------------------------- + Device Node Initialization / Removal + -------------------------------------------------------------------------- */ +#define ACPI_STA_DEFAULT (ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED | \ + ACPI_STA_DEVICE_UI | ACPI_STA_DEVICE_FUNCTIONING) + +int acpi_device_add(struct acpi_device *device, + void (*release)(struct device *)); +void acpi_init_device_object(struct acpi_device *device, acpi_handle handle, + int type, unsigned long long sta); +void acpi_device_add_finalize(struct acpi_device *device); +void acpi_free_ids(struct acpi_device *device); + /* -------------------------------------------------------------------------- Power Resource -------------------------------------------------------------------------- */ int acpi_power_init(void); +void acpi_power_resources_list_free(struct list_head *list); +int acpi_extract_power_resources(union acpi_object *package, unsigned int start, + struct list_head *list); +int acpi_add_power_resource(acpi_handle handle); +void acpi_power_add_remove_device(struct acpi_device *adev, bool add); +int acpi_power_min_system_level(struct list_head *list); int acpi_device_sleep_wake(struct acpi_device *dev, int enable, int sleep_state, int dev_state); int acpi_power_get_inferred_state(struct acpi_device *device, int *state); int acpi_power_on_resources(struct acpi_device *device, int state); int acpi_power_transition(struct acpi_device *device, int state); -int acpi_bus_init_power(struct acpi_device *device); int acpi_wakeup_device_init(void); void acpi_early_processor_set_pdc(void); @@ -98,6 +125,4 @@ static inline void suspend_nvs_restore(void) {} -------------------------------------------------------------------------- */ struct platform_device; -struct platform_device *acpi_create_platform_device(struct acpi_device *adev); - #endif /* _ACPI_INTERNAL_H_ */ diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index cb31298ca684f5d99578ada635eb2b011bd07b67..33e609f6358580647412dd0d029f065fdfb73741 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c @@ -116,14 +116,16 @@ acpi_table_print_srat_entry(struct acpi_subtable_header *header) struct acpi_srat_mem_affinity *p = (struct acpi_srat_mem_affinity *)header; ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "SRAT Memory (0x%lx length 0x%lx) in proximity domain %d %s%s\n", + "SRAT Memory (0x%lx length 0x%lx) in proximity domain %d %s%s%s\n", (unsigned long)p->base_address, (unsigned long)p->length, p->proximity_domain, (p->flags & ACPI_SRAT_MEM_ENABLED)? "enabled" : "disabled", (p->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)? - " hot-pluggable" : "")); + " hot-pluggable" : "", + (p->flags & ACPI_SRAT_MEM_NON_VOLATILE)? + " non-volatile" : "")); } #endif /* ACPI_DEBUG_OUTPUT */ break; @@ -273,7 +275,7 @@ static int __init acpi_parse_srat(struct acpi_table_header *table) static int __init acpi_table_parse_srat(enum acpi_srat_type id, - acpi_table_entry_handler handler, unsigned int max_entries) + acpi_tbl_entry_handler handler, unsigned int max_entries) { return acpi_table_parse_entries(ACPI_SIG_SRAT, sizeof(struct acpi_table_srat), id, diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index bd22f8667eed65e3889e61dcc357d85f5f3d1239..908b02d5da1b1a16a3d55ac54afca8355dbaf203 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -787,7 +787,7 @@ acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler, acpi_irq_handler = handler; acpi_irq_context = context; - if (request_irq(irq, acpi_irq, IRQF_SHARED, "acpi", acpi_irq)) { + if (request_irq(irq, acpi_irq, IRQF_SHARED | IRQF_NO_SUSPEND, "acpi", acpi_irq)) { printk(KERN_ERR PREFIX "SCI (IRQ%d) allocation failed\n", irq); acpi_irq_handler = NULL; return AE_NOT_ACQUIRED; diff --git a/drivers/acpi/pci_bind.c b/drivers/acpi/pci_bind.c deleted file mode 100644 index a1dee29beed328430491bdbff3cfe386692b06ba..0000000000000000000000000000000000000000 --- a/drivers/acpi/pci_bind.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * pci_bind.c - ACPI PCI Device Binding ($Revision: 2 $) - * - * Copyright (C) 2001, 2002 Andy Grover - * Copyright (C) 2001, 2002 Paul Diefenbaugh - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * 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 -#include -#include -#include -#include -#include -#include -#include - -#define _COMPONENT ACPI_PCI_COMPONENT -ACPI_MODULE_NAME("pci_bind"); - -static int acpi_pci_unbind(struct acpi_device *device) -{ - struct pci_dev *dev; - - dev = acpi_get_pci_dev(device->handle); - if (!dev) - goto out; - - device_set_run_wake(&dev->dev, false); - pci_acpi_remove_pm_notifier(device); - acpi_power_resource_unregister_device(&dev->dev, device->handle); - - if (!dev->subordinate) - goto out; - - acpi_pci_irq_del_prt(pci_domain_nr(dev->bus), dev->subordinate->number); - - device->ops.bind = NULL; - device->ops.unbind = NULL; - -out: - pci_dev_put(dev); - return 0; -} - -static int acpi_pci_bind(struct acpi_device *device) -{ - acpi_status status; - acpi_handle handle; - unsigned char bus; - struct pci_dev *dev; - - dev = acpi_get_pci_dev(device->handle); - if (!dev) - return 0; - - pci_acpi_add_pm_notifier(device, dev); - acpi_power_resource_register_device(&dev->dev, device->handle); - if (device->wakeup.flags.run_wake) - device_set_run_wake(&dev->dev, true); - - /* - * Install the 'bind' function to facilitate callbacks for - * children of the P2P bridge. - */ - if (dev->subordinate) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Device %04x:%02x:%02x.%d is a PCI bridge\n", - pci_domain_nr(dev->bus), dev->bus->number, - PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn))); - device->ops.bind = acpi_pci_bind; - device->ops.unbind = acpi_pci_unbind; - } - - /* - * Evaluate and parse _PRT, if exists. This code allows parsing of - * _PRT objects within the scope of non-bridge devices. Note that - * _PRTs within the scope of a PCI bridge assume the bridge's - * subordinate bus number. - * - * TBD: Can _PRTs exist within the scope of non-bridge PCI devices? - */ - status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); - if (ACPI_FAILURE(status)) - goto out; - - if (dev->subordinate) - bus = dev->subordinate->number; - else - bus = dev->bus->number; - - acpi_pci_irq_add_prt(device->handle, pci_domain_nr(dev->bus), bus); - -out: - pci_dev_put(dev); - return 0; -} - -int acpi_pci_bind_root(struct acpi_device *device) -{ - device->ops.bind = acpi_pci_bind; - device->ops.unbind = acpi_pci_unbind; - - return 0; -} diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index a12808259dfb9fdf7a1908bbb04fe13b21f422f7..ab764ed34a502aea838f4a70b0478ae73543873d 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c @@ -53,23 +53,19 @@ ACPI_MODULE_NAME("pci_link"); #define ACPI_PCI_LINK_FILE_STATUS "state" #define ACPI_PCI_LINK_MAX_POSSIBLE 16 -static int acpi_pci_link_add(struct acpi_device *device); -static int acpi_pci_link_remove(struct acpi_device *device, int type); +static int acpi_pci_link_add(struct acpi_device *device, + const struct acpi_device_id *not_used); +static void acpi_pci_link_remove(struct acpi_device *device); static const struct acpi_device_id link_device_ids[] = { {"PNP0C0F", 0}, {"", 0}, }; -MODULE_DEVICE_TABLE(acpi, link_device_ids); -static struct acpi_driver acpi_pci_link_driver = { - .name = "pci_link", - .class = ACPI_PCI_LINK_CLASS, +static struct acpi_scan_handler pci_link_handler = { .ids = link_device_ids, - .ops = { - .add = acpi_pci_link_add, - .remove = acpi_pci_link_remove, - }, + .attach = acpi_pci_link_add, + .detach = acpi_pci_link_remove, }; /* @@ -692,7 +688,8 @@ int acpi_pci_link_free_irq(acpi_handle handle) Driver Interface -------------------------------------------------------------------------- */ -static int acpi_pci_link_add(struct acpi_device *device) +static int acpi_pci_link_add(struct acpi_device *device, + const struct acpi_device_id *not_used) { int result; struct acpi_pci_link *link; @@ -746,7 +743,7 @@ static int acpi_pci_link_add(struct acpi_device *device) if (result) kfree(link); - return result; + return result < 0 ? result : 1; } static int acpi_pci_link_resume(struct acpi_pci_link *link) @@ -766,7 +763,7 @@ static void irqrouter_resume(void) } } -static int acpi_pci_link_remove(struct acpi_device *device, int type) +static void acpi_pci_link_remove(struct acpi_device *device) { struct acpi_pci_link *link; @@ -777,7 +774,6 @@ static int acpi_pci_link_remove(struct acpi_device *device, int type) mutex_unlock(&acpi_link_lock); kfree(link); - return 0; } /* @@ -874,20 +870,10 @@ static struct syscore_ops irqrouter_syscore_ops = { .resume = irqrouter_resume, }; -static int __init irqrouter_init_ops(void) -{ - if (!acpi_disabled && !acpi_noirq) - register_syscore_ops(&irqrouter_syscore_ops); - - return 0; -} - -device_initcall(irqrouter_init_ops); - -static int __init acpi_pci_link_init(void) +void __init acpi_pci_link_init(void) { if (acpi_noirq) - return 0; + return; if (acpi_irq_balance == -1) { /* no command line switch: enable balancing in IOAPIC mode */ @@ -896,11 +882,6 @@ static int __init acpi_pci_link_init(void) else acpi_irq_balance = 0; } - - if (acpi_bus_register_driver(&acpi_pci_link_driver) < 0) - return -ENODEV; - - return 0; + register_syscore_ops(&irqrouter_syscore_ops); + acpi_scan_add_handler(&pci_link_handler); } - -subsys_initcall(acpi_pci_link_init); diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 7928d4dc705618a833ccce3172ed5113307d4cff..b3cc69c5caf1e07bd93aa4111bfcbb0a0d4293b5 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -45,9 +45,9 @@ ACPI_MODULE_NAME("pci_root"); #define ACPI_PCI_ROOT_CLASS "pci_bridge" #define ACPI_PCI_ROOT_DEVICE_NAME "PCI Root Bridge" -static int acpi_pci_root_add(struct acpi_device *device); -static int acpi_pci_root_remove(struct acpi_device *device, int type); -static int acpi_pci_root_start(struct acpi_device *device); +static int acpi_pci_root_add(struct acpi_device *device, + const struct acpi_device_id *not_used); +static void acpi_pci_root_remove(struct acpi_device *device); #define ACPI_PCIE_REQ_SUPPORT (OSC_EXT_PCI_CONFIG_SUPPORT \ | OSC_ACTIVE_STATE_PWR_SUPPORT \ @@ -58,17 +58,11 @@ static const struct acpi_device_id root_device_ids[] = { {"PNP0A03", 0}, {"", 0}, }; -MODULE_DEVICE_TABLE(acpi, root_device_ids); -static struct acpi_driver acpi_pci_root_driver = { - .name = "pci_root", - .class = ACPI_PCI_ROOT_CLASS, +static struct acpi_scan_handler pci_root_handler = { .ids = root_device_ids, - .ops = { - .add = acpi_pci_root_add, - .remove = acpi_pci_root_remove, - .start = acpi_pci_root_start, - }, + .attach = acpi_pci_root_add, + .detach = acpi_pci_root_remove, }; /* Lock to protect both acpi_pci_roots and acpi_pci_drivers lists */ @@ -188,21 +182,6 @@ static acpi_status try_get_root_bridge_busnr(acpi_handle handle, return AE_OK; } -static void acpi_pci_bridge_scan(struct acpi_device *device) -{ - int status; - struct acpi_device *child = NULL; - - if (device->flags.bus_address) - if (device->parent && device->parent->ops.bind) { - status = device->parent->ops.bind(device); - if (!status) { - list_for_each_entry(child, &device->children, node) - acpi_pci_bridge_scan(child); - } - } -} - static u8 pci_osc_uuid_str[] = "33DB4D5B-1FF7-401C-9657-7441C03DD766"; static acpi_status acpi_pci_run_osc(acpi_handle handle, @@ -445,14 +424,15 @@ acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 *mask, u32 req) } EXPORT_SYMBOL(acpi_pci_osc_control_set); -static int acpi_pci_root_add(struct acpi_device *device) +static int acpi_pci_root_add(struct acpi_device *device, + const struct acpi_device_id *not_used) { unsigned long long segment, bus; acpi_status status; int result; struct acpi_pci_root *root; acpi_handle handle; - struct acpi_device *child; + struct acpi_pci_driver *driver; u32 flags, base_flags; bool is_osc_granted = false; @@ -603,21 +583,6 @@ static int acpi_pci_root_add(struct acpi_device *device) goto out_del_root; } - /* - * Attach ACPI-PCI Context - * ----------------------- - * Thus binding the ACPI and PCI devices. - */ - result = acpi_pci_bind_root(device); - if (result) - goto out_del_root; - - /* - * Scan and bind all _ADR-Based Devices - */ - list_for_each_entry(child, &device->children, node) - acpi_pci_bridge_scan(child); - /* ASPM setting */ if (is_osc_granted) { if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) @@ -632,24 +597,6 @@ static int acpi_pci_root_add(struct acpi_device *device) if (device->wakeup.flags.run_wake) device_set_run_wake(root->bus->bridge, true); - return 0; - -out_del_root: - mutex_lock(&acpi_pci_root_lock); - list_del(&root->node); - mutex_unlock(&acpi_pci_root_lock); - - acpi_pci_irq_del_prt(root->segment, root->secondary.start); -end: - kfree(root); - return result; -} - -static int acpi_pci_root_start(struct acpi_device *device) -{ - struct acpi_pci_root *root = acpi_driver_data(device); - struct acpi_pci_driver *driver; - if (system_state != SYSTEM_BOOTING) pci_assign_unassigned_bus_resources(root->bus); @@ -664,11 +611,20 @@ static int acpi_pci_root_start(struct acpi_device *device) pci_enable_bridges(root->bus); pci_bus_add_devices(root->bus); + return 1; - return 0; +out_del_root: + mutex_lock(&acpi_pci_root_lock); + list_del(&root->node); + mutex_unlock(&acpi_pci_root_lock); + + acpi_pci_irq_del_prt(root->segment, root->secondary.start); +end: + kfree(root); + return result; } -static int acpi_pci_root_remove(struct acpi_device *device, int type) +static void acpi_pci_root_remove(struct acpi_device *device) { acpi_status status; acpi_handle handle; @@ -696,21 +652,14 @@ static int acpi_pci_root_remove(struct acpi_device *device, int type) list_del(&root->node); mutex_unlock(&acpi_pci_root_lock); kfree(root); - return 0; } -static int __init acpi_pci_root_init(void) +void __init acpi_pci_root_init(void) { acpi_hest_init(); - if (acpi_pci_disabled) - return 0; - - pci_acpi_crs_quirks(); - if (acpi_bus_register_driver(&acpi_pci_root_driver) < 0) - return -ENODEV; - - return 0; + if (!acpi_pci_disabled) { + pci_acpi_crs_quirks(); + acpi_scan_add_handler(&pci_root_handler); + } } - -subsys_initcall(acpi_pci_root_init); diff --git a/drivers/acpi/pci_slot.c b/drivers/acpi/pci_slot.c index d22585f21aebc0f047e4721e268930bb61c970f9..2c630c006c2ff30a9461b6fb2e0ccb6265c5c224 100644 --- a/drivers/acpi/pci_slot.c +++ b/drivers/acpi/pci_slot.c @@ -50,13 +50,12 @@ module_param(debug, bool, 0644); ACPI_MODULE_NAME("pci_slot"); #define MY_NAME "pci_slot" -#define err(format, arg...) printk(KERN_ERR "%s: " format , MY_NAME , ## arg) -#define info(format, arg...) printk(KERN_INFO "%s: " format , MY_NAME , ## arg) +#define err(format, arg...) pr_err("%s: " format , MY_NAME , ## arg) +#define info(format, arg...) pr_info("%s: " format , MY_NAME , ## arg) #define dbg(format, arg...) \ do { \ if (debug) \ - printk(KERN_DEBUG "%s: " format, \ - MY_NAME , ## arg); \ + pr_debug("%s: " format, MY_NAME , ## arg); \ } while (0) #define SLOT_NAME_SIZE 21 /* Inspired by #define in acpiphp.h */ diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 6e7b9d5238124586ca10a000726472ff29cbc191..b820528a5fa3fa99a2c6628dd7aa0740776a402e 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include "sleep.h" @@ -58,88 +59,121 @@ ACPI_MODULE_NAME("power"); #define ACPI_POWER_RESOURCE_STATE_ON 0x01 #define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF -static int acpi_power_add(struct acpi_device *device); -static int acpi_power_remove(struct acpi_device *device, int type); - -static const struct acpi_device_id power_device_ids[] = { - {ACPI_POWER_HID, 0}, - {"", 0}, -}; -MODULE_DEVICE_TABLE(acpi, power_device_ids); - -#ifdef CONFIG_PM_SLEEP -static int acpi_power_resume(struct device *dev); -#endif -static SIMPLE_DEV_PM_OPS(acpi_power_pm, NULL, acpi_power_resume); - -static struct acpi_driver acpi_power_driver = { - .name = "power", - .class = ACPI_POWER_CLASS, - .ids = power_device_ids, - .ops = { - .add = acpi_power_add, - .remove = acpi_power_remove, - }, - .drv.pm = &acpi_power_pm, -}; - -/* - * A power managed device - * A device may rely on multiple power resources. - * */ -struct acpi_power_managed_device { - struct device *dev; /* The physical device */ - acpi_handle *handle; -}; - -struct acpi_power_resource_device { - struct acpi_power_managed_device *device; - struct acpi_power_resource_device *next; +struct acpi_power_dependent_device { + struct list_head node; + struct acpi_device *adev; + struct work_struct work; }; struct acpi_power_resource { - struct acpi_device * device; - acpi_bus_id name; + struct acpi_device device; + struct list_head list_node; + struct list_head dependent; + char *name; u32 system_level; u32 order; unsigned int ref_count; struct mutex resource_lock; +}; - /* List of devices relying on this power resource */ - struct acpi_power_resource_device *devices; - struct mutex devices_lock; +struct acpi_power_resource_entry { + struct list_head node; + struct acpi_power_resource *resource; }; -static struct list_head acpi_power_resource_list; +static LIST_HEAD(acpi_power_resource_list); +static DEFINE_MUTEX(power_resource_list_lock); /* -------------------------------------------------------------------------- Power Resource Management -------------------------------------------------------------------------- */ -static int -acpi_power_get_context(acpi_handle handle, - struct acpi_power_resource **resource) +static inline +struct acpi_power_resource *to_power_resource(struct acpi_device *device) { - int result = 0; - struct acpi_device *device = NULL; + return container_of(device, struct acpi_power_resource, device); +} + +static struct acpi_power_resource *acpi_power_get_context(acpi_handle handle) +{ + struct acpi_device *device; + if (acpi_bus_get_device(handle, &device)) + return NULL; - if (!resource) - return -ENODEV; + return to_power_resource(device); +} - result = acpi_bus_get_device(handle, &device); - if (result) { - printk(KERN_WARNING PREFIX "Getting context [%p]\n", handle); - return result; - } +static int acpi_power_resources_list_add(acpi_handle handle, + struct list_head *list) +{ + struct acpi_power_resource *resource = acpi_power_get_context(handle); + struct acpi_power_resource_entry *entry; - *resource = acpi_driver_data(device); - if (!*resource) - return -ENODEV; + if (!resource || !list) + return -EINVAL; + + entry = kzalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) + return -ENOMEM; + + entry->resource = resource; + if (!list_empty(list)) { + struct acpi_power_resource_entry *e; + list_for_each_entry(e, list, node) + if (e->resource->order > resource->order) { + list_add_tail(&entry->node, &e->node); + return 0; + } + } + list_add_tail(&entry->node, list); return 0; } +void acpi_power_resources_list_free(struct list_head *list) +{ + struct acpi_power_resource_entry *entry, *e; + + list_for_each_entry_safe(entry, e, list, node) { + list_del(&entry->node); + kfree(entry); + } +} + +int acpi_extract_power_resources(union acpi_object *package, unsigned int start, + struct list_head *list) +{ + unsigned int i; + int err = 0; + + for (i = start; i < package->package.count; i++) { + union acpi_object *element = &package->package.elements[i]; + acpi_handle rhandle; + + if (element->type != ACPI_TYPE_LOCAL_REFERENCE) { + err = -ENODATA; + break; + } + rhandle = element->reference.handle; + if (!rhandle) { + err = -ENODEV; + break; + } + err = acpi_add_power_resource(rhandle); + if (err) + break; + + err = acpi_power_resources_list_add(rhandle, list); + if (err) + break; + } + if (err) + acpi_power_resources_list_free(list); + + return err; +} + static int acpi_power_get_state(acpi_handle handle, int *state) { acpi_status status = AE_OK; @@ -167,31 +201,23 @@ static int acpi_power_get_state(acpi_handle handle, int *state) return 0; } -static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state) +static int acpi_power_get_list_state(struct list_head *list, int *state) { + struct acpi_power_resource_entry *entry; int cur_state; - int i = 0; if (!list || !state) return -EINVAL; /* The state of the list is 'on' IFF all resources are 'on'. */ - - for (i = 0; i < list->count; i++) { - struct acpi_power_resource *resource; - acpi_handle handle = list->handles[i]; + list_for_each_entry(entry, list, node) { + struct acpi_power_resource *resource = entry->resource; + acpi_handle handle = resource->device.handle; int result; - result = acpi_power_get_context(handle, &resource); - if (result) - return result; - mutex_lock(&resource->resource_lock); - result = acpi_power_get_state(handle, &cur_state); - mutex_unlock(&resource->resource_lock); - if (result) return result; @@ -203,54 +229,52 @@ static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state) cur_state ? "on" : "off")); *state = cur_state; - return 0; } -/* Resume the device when all power resources in _PR0 are on */ -static void acpi_power_on_device(struct acpi_power_managed_device *device) +static void acpi_power_resume_dependent(struct work_struct *work) { - struct acpi_device *acpi_dev; - acpi_handle handle = device->handle; + struct acpi_power_dependent_device *dep; + struct acpi_device_physical_node *pn; + struct acpi_device *adev; int state; - if (acpi_bus_get_device(handle, &acpi_dev)) + dep = container_of(work, struct acpi_power_dependent_device, work); + adev = dep->adev; + if (acpi_power_get_inferred_state(adev, &state)) return; - if(acpi_power_get_inferred_state(acpi_dev, &state)) + if (state > ACPI_STATE_D0) return; - if (state == ACPI_STATE_D0 && pm_runtime_suspended(device->dev)) - pm_request_resume(device->dev); + mutex_lock(&adev->physical_node_lock); + + list_for_each_entry(pn, &adev->physical_node_list, node) + pm_request_resume(pn->dev); + + list_for_each_entry(pn, &adev->power_dependent, node) + pm_request_resume(pn->dev); + + mutex_unlock(&adev->physical_node_lock); } static int __acpi_power_on(struct acpi_power_resource *resource) { acpi_status status = AE_OK; - status = acpi_evaluate_object(resource->device->handle, "_ON", NULL, NULL); + status = acpi_evaluate_object(resource->device.handle, "_ON", NULL, NULL); if (ACPI_FAILURE(status)) return -ENODEV; - /* Update the power resource's _device_ power state */ - resource->device->power.state = ACPI_STATE_D0; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Power resource [%s] turned on\n", resource->name)); return 0; } -static int acpi_power_on(acpi_handle handle) +static int acpi_power_on(struct acpi_power_resource *resource) { - int result = 0; - bool resume_device = false; - struct acpi_power_resource *resource = NULL; - struct acpi_power_resource_device *device_list; - - result = acpi_power_get_context(handle, &resource); - if (result) - return result; + int result = 0;; mutex_lock(&resource->resource_lock); @@ -260,39 +284,38 @@ static int acpi_power_on(acpi_handle handle) resource->name)); } else { result = __acpi_power_on(resource); - if (result) + if (result) { resource->ref_count--; - else - resume_device = true; + } else { + struct acpi_power_dependent_device *dep; + + list_for_each_entry(dep, &resource->dependent, node) + schedule_work(&dep->work); + } } mutex_unlock(&resource->resource_lock); - if (!resume_device) - return result; - - mutex_lock(&resource->devices_lock); + return result; +} - device_list = resource->devices; - while (device_list) { - acpi_power_on_device(device_list->device); - device_list = device_list->next; - } +static int __acpi_power_off(struct acpi_power_resource *resource) +{ + acpi_status status; - mutex_unlock(&resource->devices_lock); + status = acpi_evaluate_object(resource->device.handle, "_OFF", + NULL, NULL); + if (ACPI_FAILURE(status)) + return -ENODEV; - return result; + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Power resource [%s] turned off\n", + resource->name)); + return 0; } -static int acpi_power_off(acpi_handle handle) +static int acpi_power_off(struct acpi_power_resource *resource) { int result = 0; - acpi_status status = AE_OK; - struct acpi_power_resource *resource = NULL; - - result = acpi_power_get_context(handle, &resource); - if (result) - return result; mutex_lock(&resource->resource_lock); @@ -307,19 +330,10 @@ static int acpi_power_off(acpi_handle handle) ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Power resource [%s] still in use\n", resource->name)); - goto unlock; - } - - status = acpi_evaluate_object(resource->device->handle, "_OFF", NULL, NULL); - if (ACPI_FAILURE(status)) { - result = -ENODEV; } else { - /* Update the power resource's _device_ power state */ - resource->device->power.state = ACPI_STATE_D3; - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Power resource [%s] turned off\n", - resource->name)); + result = __acpi_power_off(resource); + if (result) + resource->ref_count++; } unlock: @@ -328,148 +342,202 @@ static int acpi_power_off(acpi_handle handle) return result; } -static void __acpi_power_off_list(struct acpi_handle_list *list, int num_res) +static int acpi_power_off_list(struct list_head *list) { - int i; + struct acpi_power_resource_entry *entry; + int result = 0; - for (i = num_res - 1; i >= 0 ; i--) - acpi_power_off(list->handles[i]); -} + list_for_each_entry_reverse(entry, list, node) { + result = acpi_power_off(entry->resource); + if (result) + goto err; + } + return 0; -static void acpi_power_off_list(struct acpi_handle_list *list) -{ - __acpi_power_off_list(list, list->count); + err: + list_for_each_entry_continue(entry, list, node) + acpi_power_on(entry->resource); + + return result; } -static int acpi_power_on_list(struct acpi_handle_list *list) +static int acpi_power_on_list(struct list_head *list) { + struct acpi_power_resource_entry *entry; int result = 0; - int i; - for (i = 0; i < list->count; i++) { - result = acpi_power_on(list->handles[i]); - if (result) { - __acpi_power_off_list(list, i); - break; - } + list_for_each_entry(entry, list, node) { + result = acpi_power_on(entry->resource); + if (result) + goto err; } + return 0; + + err: + list_for_each_entry_continue_reverse(entry, list, node) + acpi_power_off(entry->resource); return result; } -static void __acpi_power_resource_unregister_device(struct device *dev, - acpi_handle res_handle) +static void acpi_power_add_dependent(struct acpi_power_resource *resource, + struct acpi_device *adev) { - struct acpi_power_resource *resource = NULL; - struct acpi_power_resource_device *prev, *curr; + struct acpi_power_dependent_device *dep; - if (acpi_power_get_context(res_handle, &resource)) - return; + mutex_lock(&resource->resource_lock); + + list_for_each_entry(dep, &resource->dependent, node) + if (dep->adev == adev) + goto out; + + dep = kzalloc(sizeof(*dep), GFP_KERNEL); + if (!dep) + goto out; + + dep->adev = adev; + INIT_WORK(&dep->work, acpi_power_resume_dependent); + list_add_tail(&dep->node, &resource->dependent); - mutex_lock(&resource->devices_lock); - prev = NULL; - curr = resource->devices; - while (curr) { - if (curr->device->dev == dev) { - if (!prev) - resource->devices = curr->next; - else - prev->next = curr->next; - - kfree(curr); + out: + mutex_unlock(&resource->resource_lock); +} + +static void acpi_power_remove_dependent(struct acpi_power_resource *resource, + struct acpi_device *adev) +{ + struct acpi_power_dependent_device *dep; + struct work_struct *work = NULL; + + mutex_lock(&resource->resource_lock); + + list_for_each_entry(dep, &resource->dependent, node) + if (dep->adev == adev) { + list_del(&dep->node); + work = &dep->work; break; } - prev = curr; - curr = curr->next; + mutex_unlock(&resource->resource_lock); + + if (work) { + cancel_work_sync(work); + kfree(dep); } - mutex_unlock(&resource->devices_lock); } -/* Unlink dev from all power resources in _PR0 */ -void acpi_power_resource_unregister_device(struct device *dev, acpi_handle handle) -{ - struct acpi_device *acpi_dev; - struct acpi_handle_list *list; - int i; +static struct attribute *attrs[] = { + NULL, +}; - if (!dev || !handle) - return; +static struct attribute_group attr_groups[] = { + [ACPI_STATE_D0] = { + .name = "power_resources_D0", + .attrs = attrs, + }, + [ACPI_STATE_D1] = { + .name = "power_resources_D1", + .attrs = attrs, + }, + [ACPI_STATE_D2] = { + .name = "power_resources_D2", + .attrs = attrs, + }, + [ACPI_STATE_D3_HOT] = { + .name = "power_resources_D3hot", + .attrs = attrs, + }, +}; - if (acpi_bus_get_device(handle, &acpi_dev)) +static void acpi_power_hide_list(struct acpi_device *adev, int state) +{ + struct acpi_device_power_state *ps = &adev->power.states[state]; + struct acpi_power_resource_entry *entry; + + if (list_empty(&ps->resources)) return; - list = &acpi_dev->power.states[ACPI_STATE_D0].resources; + list_for_each_entry_reverse(entry, &ps->resources, node) { + struct acpi_device *res_dev = &entry->resource->device; - for (i = 0; i < list->count; i++) - __acpi_power_resource_unregister_device(dev, - list->handles[i]); + sysfs_remove_link_from_group(&adev->dev.kobj, + attr_groups[state].name, + dev_name(&res_dev->dev)); + } + sysfs_remove_group(&adev->dev.kobj, &attr_groups[state]); } -EXPORT_SYMBOL_GPL(acpi_power_resource_unregister_device); -static int __acpi_power_resource_register_device( - struct acpi_power_managed_device *powered_device, acpi_handle handle) +static void acpi_power_expose_list(struct acpi_device *adev, int state) { - struct acpi_power_resource *resource = NULL; - struct acpi_power_resource_device *power_resource_device; - int result; - - result = acpi_power_get_context(handle, &resource); - if (result) - return result; + struct acpi_device_power_state *ps = &adev->power.states[state]; + struct acpi_power_resource_entry *entry; + int ret; - power_resource_device = kzalloc( - sizeof(*power_resource_device), GFP_KERNEL); - if (!power_resource_device) - return -ENOMEM; + if (list_empty(&ps->resources)) + return; - power_resource_device->device = powered_device; + ret = sysfs_create_group(&adev->dev.kobj, &attr_groups[state]); + if (ret) + return; - mutex_lock(&resource->devices_lock); - power_resource_device->next = resource->devices; - resource->devices = power_resource_device; - mutex_unlock(&resource->devices_lock); + list_for_each_entry(entry, &ps->resources, node) { + struct acpi_device *res_dev = &entry->resource->device; - return 0; + ret = sysfs_add_link_to_group(&adev->dev.kobj, + attr_groups[state].name, + &res_dev->dev.kobj, + dev_name(&res_dev->dev)); + if (ret) { + acpi_power_hide_list(adev, state); + break; + } + } } -/* Link dev to all power resources in _PR0 */ -int acpi_power_resource_register_device(struct device *dev, acpi_handle handle) +void acpi_power_add_remove_device(struct acpi_device *adev, bool add) { - struct acpi_device *acpi_dev; - struct acpi_handle_list *list; - struct acpi_power_managed_device *powered_device; - int i, ret; + struct acpi_device_power_state *ps; + struct acpi_power_resource_entry *entry; + int state; - if (!dev || !handle) - return -ENODEV; + if (!adev->power.flags.power_resources) + return; - ret = acpi_bus_get_device(handle, &acpi_dev); - if (ret || !acpi_dev->power.flags.power_resources) - return -ENODEV; + ps = &adev->power.states[ACPI_STATE_D0]; + list_for_each_entry(entry, &ps->resources, node) { + struct acpi_power_resource *resource = entry->resource; - powered_device = kzalloc(sizeof(*powered_device), GFP_KERNEL); - if (!powered_device) - return -ENOMEM; + if (add) + acpi_power_add_dependent(resource, adev); + else + acpi_power_remove_dependent(resource, adev); + } - powered_device->dev = dev; - powered_device->handle = handle; + for (state = ACPI_STATE_D0; state <= ACPI_STATE_D3_HOT; state++) { + if (add) + acpi_power_expose_list(adev, state); + else + acpi_power_hide_list(adev, state); + } +} - list = &acpi_dev->power.states[ACPI_STATE_D0].resources; +int acpi_power_min_system_level(struct list_head *list) +{ + struct acpi_power_resource_entry *entry; + int system_level = 5; - for (i = 0; i < list->count; i++) { - ret = __acpi_power_resource_register_device(powered_device, - list->handles[i]); + list_for_each_entry(entry, list, node) { + struct acpi_power_resource *resource = entry->resource; - if (ret) { - acpi_power_resource_unregister_device(dev, handle); - break; - } + if (system_level > resource->system_level) + system_level = resource->system_level; } - - return ret; + return system_level; } -EXPORT_SYMBOL_GPL(acpi_power_resource_register_device); + +/* -------------------------------------------------------------------------- + Device Power Management + -------------------------------------------------------------------------- */ /** * acpi_device_sleep_wake - execute _DSW (Device Sleep Wake) or (deprecated in @@ -542,7 +610,7 @@ int acpi_device_sleep_wake(struct acpi_device *dev, */ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state) { - int i, err = 0; + int err = 0; if (!dev || !dev->wakeup.flags.valid) return -EINVAL; @@ -552,24 +620,17 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state) if (dev->wakeup.prepare_count++) goto out; - /* Open power resource */ - for (i = 0; i < dev->wakeup.resources.count; i++) { - int ret = acpi_power_on(dev->wakeup.resources.handles[i]); - if (ret) { - printk(KERN_ERR PREFIX "Transition power state\n"); - dev->wakeup.flags.valid = 0; - err = -ENODEV; - goto err_out; - } + err = acpi_power_on_list(&dev->wakeup.resources); + if (err) { + dev_err(&dev->dev, "Cannot turn wakeup power resources on\n"); + dev->wakeup.flags.valid = 0; + } else { + /* + * Passing 3 as the third argument below means the device may be + * put into arbitrary power state afterward. + */ + err = acpi_device_sleep_wake(dev, 1, sleep_state, 3); } - - /* - * Passing 3 as the third argument below means the device may be placed - * in arbitrary power state afterwards. - */ - err = acpi_device_sleep_wake(dev, 1, sleep_state, 3); - - err_out: if (err) dev->wakeup.prepare_count = 0; @@ -586,7 +647,7 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state) */ int acpi_disable_wakeup_device_power(struct acpi_device *dev) { - int i, err = 0; + int err = 0; if (!dev || !dev->wakeup.flags.valid) return -EINVAL; @@ -607,15 +668,10 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev) if (err) goto out; - /* Close power resource */ - for (i = 0; i < dev->wakeup.resources.count; i++) { - int ret = acpi_power_off(dev->wakeup.resources.handles[i]); - if (ret) { - printk(KERN_ERR PREFIX "Transition power state\n"); - dev->wakeup.flags.valid = 0; - err = -ENODEV; - goto out; - } + err = acpi_power_off_list(&dev->wakeup.resources); + if (err) { + dev_err(&dev->dev, "Cannot turn wakeup power resources off\n"); + dev->wakeup.flags.valid = 0; } out: @@ -623,14 +679,9 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev) return err; } -/* -------------------------------------------------------------------------- - Device Power Management - -------------------------------------------------------------------------- */ - int acpi_power_get_inferred_state(struct acpi_device *device, int *state) { int result = 0; - struct acpi_handle_list *list = NULL; int list_state = 0; int i = 0; @@ -642,8 +693,9 @@ int acpi_power_get_inferred_state(struct acpi_device *device, int *state) * required for a given D-state are 'on'. */ for (i = ACPI_STATE_D0; i <= ACPI_STATE_D3_HOT; i++) { - list = &device->power.states[i].resources; - if (list->count < 1) + struct list_head *list = &device->power.states[i].resources; + + if (list_empty(list)) continue; result = acpi_power_get_list_state(list, &list_state); @@ -662,7 +714,7 @@ int acpi_power_get_inferred_state(struct acpi_device *device, int *state) int acpi_power_on_resources(struct acpi_device *device, int state) { - if (!device || state < ACPI_STATE_D0 || state > ACPI_STATE_D3) + if (!device || state < ACPI_STATE_D0 || state > ACPI_STATE_D3_HOT) return -EINVAL; return acpi_power_on_list(&device->power.states[state].resources); @@ -675,7 +727,7 @@ int acpi_power_transition(struct acpi_device *device, int state) if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3_COLD)) return -EINVAL; - if (device->power.state == state) + if (device->power.state == state || !device->flags.power_manageable) return 0; if ((device->power.state < ACPI_STATE_D0) @@ -703,118 +755,126 @@ int acpi_power_transition(struct acpi_device *device, int state) return result; } -/* -------------------------------------------------------------------------- - Driver Interface - -------------------------------------------------------------------------- */ +static void acpi_release_power_resource(struct device *dev) +{ + struct acpi_device *device = to_acpi_device(dev); + struct acpi_power_resource *resource; + + resource = container_of(device, struct acpi_power_resource, device); + + mutex_lock(&power_resource_list_lock); + list_del(&resource->list_node); + mutex_unlock(&power_resource_list_lock); + + acpi_free_ids(device); + kfree(resource); +} -static int acpi_power_add(struct acpi_device *device) +static ssize_t acpi_power_in_use_show(struct device *dev, + struct device_attribute *attr, + char *buf) { + struct acpi_power_resource *resource; + + resource = to_power_resource(to_acpi_device(dev)); + return sprintf(buf, "%u\n", !!resource->ref_count); +} +static DEVICE_ATTR(resource_in_use, 0444, acpi_power_in_use_show, NULL); + +static void acpi_power_sysfs_remove(struct acpi_device *device) { - int result = 0, state; - acpi_status status = AE_OK; - struct acpi_power_resource *resource = NULL; + device_remove_file(&device->dev, &dev_attr_resource_in_use); +} + +int acpi_add_power_resource(acpi_handle handle) +{ + struct acpi_power_resource *resource; + struct acpi_device *device = NULL; union acpi_object acpi_object; struct acpi_buffer buffer = { sizeof(acpi_object), &acpi_object }; + acpi_status status; + int state, result = -ENODEV; + acpi_bus_get_device(handle, &device); + if (device) + return 0; - if (!device) - return -EINVAL; - - resource = kzalloc(sizeof(struct acpi_power_resource), GFP_KERNEL); + resource = kzalloc(sizeof(*resource), GFP_KERNEL); if (!resource) return -ENOMEM; - resource->device = device; + device = &resource->device; + acpi_init_device_object(device, handle, ACPI_BUS_TYPE_POWER, + ACPI_STA_DEFAULT); mutex_init(&resource->resource_lock); - mutex_init(&resource->devices_lock); - strcpy(resource->name, device->pnp.bus_id); + INIT_LIST_HEAD(&resource->dependent); + resource->name = device->pnp.bus_id; strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_POWER_CLASS); - device->driver_data = resource; + device->power.state = ACPI_STATE_UNKNOWN; /* Evalute the object to get the system level and resource order. */ - status = acpi_evaluate_object(device->handle, NULL, NULL, &buffer); - if (ACPI_FAILURE(status)) { - result = -ENODEV; - goto end; - } + status = acpi_evaluate_object(handle, NULL, NULL, &buffer); + if (ACPI_FAILURE(status)) + goto err; + resource->system_level = acpi_object.power_resource.system_level; resource->order = acpi_object.power_resource.resource_order; - result = acpi_power_get_state(device->handle, &state); + result = acpi_power_get_state(handle, &state); if (result) - goto end; - - switch (state) { - case ACPI_POWER_RESOURCE_STATE_ON: - device->power.state = ACPI_STATE_D0; - break; - case ACPI_POWER_RESOURCE_STATE_OFF: - device->power.state = ACPI_STATE_D3; - break; - default: - device->power.state = ACPI_STATE_UNKNOWN; - break; - } + goto err; printk(KERN_INFO PREFIX "%s [%s] (%s)\n", acpi_device_name(device), acpi_device_bid(device), state ? "on" : "off"); - end: + device->flags.match_driver = true; + result = acpi_device_add(device, acpi_release_power_resource); if (result) - kfree(resource); + goto err; - return result; -} - -static int acpi_power_remove(struct acpi_device *device, int type) -{ - struct acpi_power_resource *resource; - - if (!device) - return -EINVAL; - - resource = acpi_driver_data(device); - if (!resource) - return -EINVAL; - - kfree(resource); + if (!device_create_file(&device->dev, &dev_attr_resource_in_use)) + device->remove = acpi_power_sysfs_remove; + mutex_lock(&power_resource_list_lock); + list_add(&resource->list_node, &acpi_power_resource_list); + mutex_unlock(&power_resource_list_lock); + acpi_device_add_finalize(device); return 0; + + err: + acpi_release_power_resource(&device->dev); + return result; } -#ifdef CONFIG_PM_SLEEP -static int acpi_power_resume(struct device *dev) +#ifdef CONFIG_ACPI_SLEEP +void acpi_resume_power_resources(void) { - int result = 0, state; - struct acpi_device *device; struct acpi_power_resource *resource; - if (!dev) - return -EINVAL; + mutex_lock(&power_resource_list_lock); - device = to_acpi_device(dev); - resource = acpi_driver_data(device); - if (!resource) - return -EINVAL; + list_for_each_entry(resource, &acpi_power_resource_list, list_node) { + int result, state; - mutex_lock(&resource->resource_lock); + mutex_lock(&resource->resource_lock); - result = acpi_power_get_state(device->handle, &state); - if (result) - goto unlock; + result = acpi_power_get_state(resource->device.handle, &state); + if (result) + continue; - if (state == ACPI_POWER_RESOURCE_STATE_OFF && resource->ref_count) - result = __acpi_power_on(resource); + if (state == ACPI_POWER_RESOURCE_STATE_OFF + && resource->ref_count) { + dev_info(&resource->device.dev, "Turning ON\n"); + __acpi_power_on(resource); + } else if (state == ACPI_POWER_RESOURCE_STATE_ON + && !resource->ref_count) { + dev_info(&resource->device.dev, "Turning OFF\n"); + __acpi_power_off(resource); + } - unlock: - mutex_unlock(&resource->resource_lock); + mutex_unlock(&resource->resource_lock); + } - return result; + mutex_unlock(&power_resource_list_lock); } #endif - -int __init acpi_power_init(void) -{ - INIT_LIST_HEAD(&acpi_power_resource_list); - return acpi_bus_register_driver(&acpi_power_driver); -} diff --git a/drivers/acpi/proc.c b/drivers/acpi/proc.c index ef98796b3824fd0895b5e27a5d6b2d1c14949b49..52ce76725c2024bfea9bc20602ea239c0bc011ff 100644 --- a/drivers/acpi/proc.c +++ b/drivers/acpi/proc.c @@ -311,11 +311,12 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset) dev->pnp.bus_id, (u32) dev->wakeup.sleep_state); - if (!dev->physical_node_count) + if (!dev->physical_node_count) { seq_printf(seq, "%c%-8s\n", - dev->wakeup.flags.run_wake ? - '*' : ' ', "disabled"); - else { + dev->wakeup.flags.run_wake ? '*' : ' ', + device_may_wakeup(&dev->dev) ? + "enabled" : "disabled"); + } else { struct device *ldev; list_for_each_entry(entry, &dev->physical_node_list, node) { diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index e83311bf1ebdaaaea1adbf2de1351cca907d3465..cbf1f122666bfa97dd3bc75ca2fe148918659569 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -81,7 +81,7 @@ MODULE_DESCRIPTION("ACPI Processor Driver"); MODULE_LICENSE("GPL"); static int acpi_processor_add(struct acpi_device *device); -static int acpi_processor_remove(struct acpi_device *device, int type); +static int acpi_processor_remove(struct acpi_device *device); static void acpi_processor_notify(struct acpi_device *device, u32 event); static acpi_status acpi_processor_hotadd_init(struct acpi_processor *pr); static int acpi_processor_handle_eject(struct acpi_processor *pr); @@ -610,7 +610,7 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device) return result; } -static int acpi_processor_remove(struct acpi_device *device, int type) +static int acpi_processor_remove(struct acpi_device *device) { struct acpi_processor *pr = NULL; @@ -623,7 +623,7 @@ static int acpi_processor_remove(struct acpi_device *device, int type) if (pr->id >= nr_cpu_ids) goto free; - if (type == ACPI_BUS_REMOVAL_EJECT) { + if (device->removal_type == ACPI_BUS_REMOVAL_EJECT) { if (acpi_processor_handle_eject(pr)) return -EINVAL; } @@ -677,36 +677,17 @@ static int is_processor_present(acpi_handle handle) return 0; } -static -int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device) -{ - acpi_handle phandle; - struct acpi_device *pdev; - - - if (acpi_get_parent(handle, &phandle)) { - return -ENODEV; - } - - if (acpi_bus_get_device(phandle, &pdev)) { - return -ENODEV; - } - - if (acpi_bus_add(device, pdev, handle, ACPI_BUS_TYPE_PROCESSOR)) { - return -ENODEV; - } - - return 0; -} - static void acpi_processor_hotplug_notify(acpi_handle handle, u32 event, void *data) { struct acpi_device *device = NULL; struct acpi_eject_event *ej_event = NULL; u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */ + acpi_status status; int result; + acpi_scan_lock_acquire(); + switch (event) { case ACPI_NOTIFY_BUS_CHECK: case ACPI_NOTIFY_DEVICE_CHECK: @@ -721,12 +702,16 @@ static void acpi_processor_hotplug_notify(acpi_handle handle, if (!acpi_bus_get_device(handle, &device)) break; - result = acpi_processor_device_add(handle, &device); + result = acpi_bus_scan(handle); if (result) { acpi_handle_err(handle, "Unable to add the device\n"); break; } - + result = acpi_bus_get_device(handle, &device); + if (result) { + acpi_handle_err(handle, "Missing device object\n"); + break; + } ost_code = ACPI_OST_SC_SUCCESS; break; @@ -751,25 +736,32 @@ static void acpi_processor_hotplug_notify(acpi_handle handle, break; } - ej_event->handle = handle; + get_device(&device->dev); + ej_event->device = device; ej_event->event = ACPI_NOTIFY_EJECT_REQUEST; - acpi_os_hotplug_execute(acpi_bus_hot_remove_device, - (void *)ej_event); - - /* eject is performed asynchronously */ - return; + /* The eject is carried out asynchronously. */ + status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, + ej_event); + if (ACPI_FAILURE(status)) { + put_device(&device->dev); + kfree(ej_event); + break; + } + goto out; default: ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unsupported event [0x%x]\n", event)); /* non-hotplug event; possibly handled by other handler */ - return; + goto out; } /* Inform firmware that the hotplug operation has completed */ (void) acpi_evaluate_hotplug_ost(handle, event, ost_code, NULL); - return; + + out: + acpi_scan_lock_release(); } static acpi_status is_processor_device(acpi_handle handle) diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index ed9a1cc690be5fa8cd3844394128216350904a7e..fc95308e9a114896289922869ff068f486fdf788 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -28,19 +28,12 @@ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -#include #include -#include -#include -#include #include #include -#include -#include /* need_resched() */ -#include +#include /* need_resched() */ #include #include -#include /* * Include the apic definitions for x86 to have the APIC timer related defines @@ -52,22 +45,14 @@ #include #endif -#include -#include - #include #include -#include #define PREFIX "ACPI: " #define ACPI_PROCESSOR_CLASS "processor" #define _COMPONENT ACPI_PROCESSOR_COMPONENT ACPI_MODULE_NAME("processor_idle"); -#define PM_TIMER_TICK_NS (1000000000ULL/PM_TIMER_FREQUENCY) -#define C2_OVERHEAD 1 /* 1us */ -#define C3_OVERHEAD 1 /* 1us */ -#define PM_TIMER_TICKS_TO_US(p) (((p) * 1000)/(PM_TIMER_FREQUENCY/1000)) static unsigned int max_cstate __read_mostly = ACPI_PROCESSOR_MAX_POWER; module_param(max_cstate, uint, 0000); @@ -81,10 +66,11 @@ module_param(latency_factor, uint, 0644); static DEFINE_PER_CPU(struct cpuidle_device *, acpi_cpuidle_device); +static struct acpi_processor_cx *acpi_cstate[CPUIDLE_STATE_MAX]; + static int disabled_by_idle_boot_param(void) { return boot_option_idle_override == IDLE_POLL || - boot_option_idle_override == IDLE_FORCE_MWAIT || boot_option_idle_override == IDLE_HALT; } @@ -736,8 +722,7 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) { struct acpi_processor *pr; - struct cpuidle_state_usage *state_usage = &dev->states_usage[index]; - struct acpi_processor_cx *cx = cpuidle_get_statedata(state_usage); + struct acpi_processor_cx *cx = acpi_cstate[index]; pr = __this_cpu_read(processors); @@ -760,8 +745,7 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev, */ static int acpi_idle_play_dead(struct cpuidle_device *dev, int index) { - struct cpuidle_state_usage *state_usage = &dev->states_usage[index]; - struct acpi_processor_cx *cx = cpuidle_get_statedata(state_usage); + struct acpi_processor_cx *cx = acpi_cstate[index]; ACPI_FLUSH_CPU_CACHE(); @@ -791,8 +775,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) { struct acpi_processor *pr; - struct cpuidle_state_usage *state_usage = &dev->states_usage[index]; - struct acpi_processor_cx *cx = cpuidle_get_statedata(state_usage); + struct acpi_processor_cx *cx = acpi_cstate[index]; pr = __this_cpu_read(processors); @@ -850,8 +833,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) { struct acpi_processor *pr; - struct cpuidle_state_usage *state_usage = &dev->states_usage[index]; - struct acpi_processor_cx *cx = cpuidle_get_statedata(state_usage); + struct acpi_processor_cx *cx = acpi_cstate[index]; pr = __this_cpu_read(processors); @@ -943,13 +925,13 @@ struct cpuidle_driver acpi_idle_driver = { * device i.e. per-cpu data * * @pr: the ACPI processor + * @dev : the cpuidle device */ -static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr) +static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr, + struct cpuidle_device *dev) { int i, count = CPUIDLE_DRIVER_STATE_START; struct acpi_processor_cx *cx; - struct cpuidle_state_usage *state_usage; - struct cpuidle_device *dev = per_cpu(acpi_cpuidle_device, pr->id); if (!pr->flags.power_setup_done) return -EINVAL; @@ -968,7 +950,6 @@ static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr) for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++) { cx = &pr->power.states[i]; - state_usage = &dev->states_usage[count]; if (!cx->valid) continue; @@ -979,8 +960,7 @@ static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr) !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED)) continue; #endif - - cpuidle_set_statedata(state_usage, cx); + acpi_cstate[count] = cx; count++; if (count == CPUIDLE_STATE_MAX) @@ -1104,7 +1084,7 @@ int acpi_processor_hotplug(struct acpi_processor *pr) cpuidle_disable_device(dev); acpi_processor_get_power_info(pr); if (pr->flags.power) { - acpi_processor_setup_cpuidle_cx(pr); + acpi_processor_setup_cpuidle_cx(pr, dev); ret = cpuidle_enable_device(dev); } cpuidle_resume_and_unlock(); @@ -1162,8 +1142,8 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr) continue; acpi_processor_get_power_info(_pr); if (_pr->flags.power) { - acpi_processor_setup_cpuidle_cx(_pr); dev = per_cpu(acpi_cpuidle_device, cpu); + acpi_processor_setup_cpuidle_cx(_pr, dev); cpuidle_enable_device(dev); } } @@ -1232,7 +1212,7 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr) return -ENOMEM; per_cpu(acpi_cpuidle_device, pr->id) = dev; - acpi_processor_setup_cpuidle_cx(pr); + acpi_processor_setup_cpuidle_cx(pr, dev); /* Register per-cpu cpuidle_device. Cpuidle driver * must already be registered before registering device diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index ff0740e0a9c248fc932992e56d23540a59489a55..e523245643acc6c65d68339c64fbf7e00ef09f95 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -130,7 +130,7 @@ struct acpi_sbs { #define to_acpi_sbs(x) container_of(x, struct acpi_sbs, charger) -static int acpi_sbs_remove(struct acpi_device *device, int type); +static int acpi_sbs_remove(struct acpi_device *device); static int acpi_battery_get_state(struct acpi_battery *battery); static inline int battery_scale(int log) @@ -949,11 +949,11 @@ static int acpi_sbs_add(struct acpi_device *device) acpi_smbus_register_callback(sbs->hc, acpi_sbs_callback, sbs); end: if (result) - acpi_sbs_remove(device, 0); + acpi_sbs_remove(device); return result; } -static int acpi_sbs_remove(struct acpi_device *device, int type) +static int acpi_sbs_remove(struct acpi_device *device) { struct acpi_sbs *sbs; int id; diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c index cf6129a8af7c97619809b19e6fc46a5be010dd66..b78bc605837e19a8f7461f48a59cdc90d64f5128 100644 --- a/drivers/acpi/sbshc.c +++ b/drivers/acpi/sbshc.c @@ -33,7 +33,7 @@ struct acpi_smb_hc { }; static int acpi_smbus_hc_add(struct acpi_device *device); -static int acpi_smbus_hc_remove(struct acpi_device *device, int type); +static int acpi_smbus_hc_remove(struct acpi_device *device); static const struct acpi_device_id sbs_device_ids[] = { {"ACPI0001", 0}, @@ -296,7 +296,7 @@ static int acpi_smbus_hc_add(struct acpi_device *device) extern void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit); -static int acpi_smbus_hc_remove(struct acpi_device *device, int type) +static int acpi_smbus_hc_remove(struct acpi_device *device) { struct acpi_smb_hc *hc; diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index c88be6c37c309b79b147ea683b9e177b1b8cca33..daee7497efd30137f2dddef2497f9968555d4e26 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -29,29 +29,10 @@ extern struct acpi_device *acpi_root; static const char *dummy_hid = "device"; -/* - * The following ACPI IDs are known to be suitable for representing as - * platform devices. - */ -static const struct acpi_device_id acpi_platform_device_ids[] = { - - { "PNP0D40" }, - - /* Haswell LPSS devices */ - { "INT33C0", 0 }, - { "INT33C1", 0 }, - { "INT33C2", 0 }, - { "INT33C3", 0 }, - { "INT33C4", 0 }, - { "INT33C5", 0 }, - { "INT33C6", 0 }, - { "INT33C7", 0 }, - - { } -}; - static LIST_HEAD(acpi_device_list); static LIST_HEAD(acpi_bus_id_list); +static DEFINE_MUTEX(acpi_scan_lock); +static LIST_HEAD(acpi_scan_handlers_list); DEFINE_MUTEX(acpi_device_lock); LIST_HEAD(acpi_wakeup_device_list); @@ -61,6 +42,27 @@ struct acpi_device_bus_id{ struct list_head node; }; +void acpi_scan_lock_acquire(void) +{ + mutex_lock(&acpi_scan_lock); +} +EXPORT_SYMBOL_GPL(acpi_scan_lock_acquire); + +void acpi_scan_lock_release(void) +{ + mutex_unlock(&acpi_scan_lock); +} +EXPORT_SYMBOL_GPL(acpi_scan_lock_release); + +int acpi_scan_add_handler(struct acpi_scan_handler *handler) +{ + if (!handler || !handler->attach) + return -EINVAL; + + list_add_tail(&handler->list_node, &acpi_scan_handlers_list); + return 0; +} + /* * Creates hid/cid(s) string needed for modalias and uevent * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get: @@ -115,39 +117,32 @@ static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL); */ void acpi_bus_hot_remove_device(void *context) { - struct acpi_eject_event *ej_event = (struct acpi_eject_event *) context; - struct acpi_device *device; - acpi_handle handle = ej_event->handle; + struct acpi_eject_event *ej_event = context; + struct acpi_device *device = ej_event->device; + acpi_handle handle = device->handle; acpi_handle temp; struct acpi_object_list arg_list; union acpi_object arg; acpi_status status = AE_OK; u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */ - if (acpi_bus_get_device(handle, &device)) - goto err_out; + mutex_lock(&acpi_scan_lock); - if (!device) - goto err_out; + /* If there is no handle, the device node has been unregistered. */ + if (!device->handle) { + dev_dbg(&device->dev, "ACPI handle missing\n"); + put_device(&device->dev); + goto out; + } ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Hot-removing device %s...\n", dev_name(&device->dev))); - if (acpi_bus_trim(device, 1)) { - printk(KERN_ERR PREFIX - "Removing device failed\n"); - goto err_out; - } - - /* device has been freed */ + acpi_bus_trim(device); + /* Device node has been unregistered. */ + put_device(&device->dev); device = NULL; - /* power off device */ - status = acpi_evaluate_object(handle, "_PS3", NULL, NULL); - if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) - printk(KERN_WARNING PREFIX - "Power-off device failed\n"); - if (ACPI_SUCCESS(acpi_get_handle(handle, "_LCK", &temp))) { arg_list.count = 1; arg_list.pointer = &arg; @@ -167,23 +162,46 @@ void acpi_bus_hot_remove_device(void *context) status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL); if (ACPI_FAILURE(status)) { if (status != AE_NOT_FOUND) - printk(KERN_WARNING PREFIX - "Eject device failed\n"); - goto err_out; - } + acpi_handle_warn(handle, "Eject failed\n"); - kfree(context); - return; + /* Tell the firmware the hot-remove operation has failed. */ + acpi_evaluate_hotplug_ost(handle, ej_event->event, + ost_code, NULL); + } -err_out: - /* Inform firmware the hot-remove operation has completed w/ error */ - (void) acpi_evaluate_hotplug_ost(handle, - ej_event->event, ost_code, NULL); + out: + mutex_unlock(&acpi_scan_lock); kfree(context); return; } EXPORT_SYMBOL(acpi_bus_hot_remove_device); +static ssize_t real_power_state_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct acpi_device *adev = to_acpi_device(dev); + int state; + int ret; + + ret = acpi_device_get_power(adev, &state); + if (ret) + return ret; + + return sprintf(buf, "%s\n", acpi_power_state_string(state)); +} + +static DEVICE_ATTR(real_power_state, 0444, real_power_state_show, NULL); + +static ssize_t power_state_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct acpi_device *adev = to_acpi_device(dev); + + return sprintf(buf, "%s\n", acpi_power_state_string(adev->power.state)); +} + +static DEVICE_ATTR(power_state, 0444, power_state_show, NULL); + static ssize_t acpi_eject_store(struct device *d, struct device_attribute *attr, const char *buf, size_t count) @@ -197,12 +215,10 @@ acpi_eject_store(struct device *d, struct device_attribute *attr, if ((!count) || (buf[0] != '1')) { return -EINVAL; } -#ifndef FORCE_EJECT - if (acpi_device->driver == NULL) { + if (!acpi_device->driver && !acpi_device->handler) { ret = -ENODEV; goto err; } -#endif status = acpi_get_type(acpi_device->handle, &type); if (ACPI_FAILURE(status) || (!acpi_device->flags.ejectable)) { ret = -ENODEV; @@ -215,7 +231,8 @@ acpi_eject_store(struct device *d, struct device_attribute *attr, goto err; } - ej_event->handle = acpi_device->handle; + get_device(&acpi_device->dev); + ej_event->device = acpi_device; if (acpi_device->flags.eject_pending) { /* event originated from ACPI eject notification */ ej_event->event = ACPI_NOTIFY_EJECT_REQUEST; @@ -223,11 +240,15 @@ acpi_eject_store(struct device *d, struct device_attribute *attr, } else { /* event originated from user */ ej_event->event = ACPI_OST_EC_OSPM_EJECT; - (void) acpi_evaluate_hotplug_ost(ej_event->handle, + (void) acpi_evaluate_hotplug_ost(acpi_device->handle, ej_event->event, ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); } - acpi_os_hotplug_execute(acpi_bus_hot_remove_device, (void *)ej_event); + status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, ej_event); + if (ACPI_FAILURE(status)) { + put_device(&acpi_device->dev); + kfree(ej_event); + } err: return ret; } @@ -375,8 +396,22 @@ static int acpi_device_setup_files(struct acpi_device *dev) * hot-removal function from userland. */ status = acpi_get_handle(dev->handle, "_EJ0", &temp); - if (ACPI_SUCCESS(status)) + if (ACPI_SUCCESS(status)) { result = device_create_file(&dev->dev, &dev_attr_eject); + if (result) + return result; + } + + if (dev->flags.power_manageable) { + result = device_create_file(&dev->dev, &dev_attr_power_state); + if (result) + return result; + + if (dev->power.flags.power_resources) + result = device_create_file(&dev->dev, + &dev_attr_real_power_state); + } + end: return result; } @@ -386,6 +421,13 @@ static void acpi_device_remove_files(struct acpi_device *dev) acpi_status status; acpi_handle temp; + if (dev->flags.power_manageable) { + device_remove_file(&dev->dev, &dev_attr_power_state); + if (dev->power.flags.power_resources) + device_remove_file(&dev->dev, + &dev_attr_real_power_state); + } + /* * If device has _STR, remove 'description' file */ @@ -454,9 +496,9 @@ const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids, const struct device *dev) { struct acpi_device *adev; + acpi_handle handle = ACPI_HANDLE(dev); - if (!ids || !ACPI_HANDLE(dev) - || ACPI_FAILURE(acpi_bus_get_device(ACPI_HANDLE(dev), &adev))) + if (!ids || !handle || acpi_bus_get_device(handle, &adev)) return NULL; return __acpi_match_device(adev, ids); @@ -470,7 +512,7 @@ int acpi_match_device_ids(struct acpi_device *device, } EXPORT_SYMBOL(acpi_match_device_ids); -static void acpi_free_ids(struct acpi_device *device) +void acpi_free_ids(struct acpi_device *device) { struct acpi_hardware_id *id, *tmp; @@ -478,6 +520,23 @@ static void acpi_free_ids(struct acpi_device *device) kfree(id->id); kfree(id); } + kfree(device->pnp.unique_id); +} + +static void acpi_free_power_resources_lists(struct acpi_device *device) +{ + int i; + + if (device->wakeup.flags.valid) + acpi_power_resources_list_free(&device->wakeup.resources); + + if (!device->flags.power_manageable) + return; + + for (i = ACPI_STATE_D0; i <= ACPI_STATE_D3_HOT; i++) { + struct acpi_device_power_state *ps = &device->power.states[i]; + acpi_power_resources_list_free(&ps->resources); + } } static void acpi_device_release(struct device *dev) @@ -485,7 +544,7 @@ static void acpi_device_release(struct device *dev) struct acpi_device *acpi_dev = to_acpi_device(dev); acpi_free_ids(acpi_dev); - kfree(acpi_dev->pnp.unique_id); + acpi_free_power_resources_lists(acpi_dev); kfree(acpi_dev); } @@ -494,7 +553,8 @@ static int acpi_bus_match(struct device *dev, struct device_driver *drv) struct acpi_device *acpi_dev = to_acpi_device(dev); struct acpi_driver *acpi_drv = to_acpi_driver(drv); - return !acpi_match_device_ids(acpi_dev, acpi_drv->ids); + return acpi_dev->flags.match_driver + && !acpi_match_device_ids(acpi_dev, acpi_drv->ids); } static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env) @@ -570,7 +630,6 @@ static void acpi_device_remove_notify_handler(struct acpi_device *device) } static int acpi_bus_driver_init(struct acpi_device *, struct acpi_driver *); -static int acpi_start_single_object(struct acpi_device *); static int acpi_device_probe(struct device * dev) { struct acpi_device *acpi_dev = to_acpi_device(dev); @@ -579,15 +638,13 @@ static int acpi_device_probe(struct device * dev) ret = acpi_bus_driver_init(acpi_dev, acpi_drv); if (!ret) { - if (acpi_dev->bus_ops.acpi_op_start) - acpi_start_single_object(acpi_dev); - if (acpi_drv->ops.notify) { ret = acpi_device_install_notify_handler(acpi_dev); if (ret) { if (acpi_drv->ops.remove) - acpi_drv->ops.remove(acpi_dev, - acpi_dev->removal_type); + acpi_drv->ops.remove(acpi_dev); + acpi_dev->driver = NULL; + acpi_dev->driver_data = NULL; return ret; } } @@ -609,7 +666,7 @@ static int acpi_device_remove(struct device * dev) if (acpi_drv->ops.notify) acpi_device_remove_notify_handler(acpi_dev); if (acpi_drv->ops.remove) - acpi_drv->ops.remove(acpi_dev, acpi_dev->removal_type); + acpi_drv->ops.remove(acpi_dev); } acpi_dev->driver = NULL; acpi_dev->driver_data = NULL; @@ -626,12 +683,25 @@ struct bus_type acpi_bus_type = { .uevent = acpi_device_uevent, }; -static int acpi_device_register(struct acpi_device *device) +int acpi_device_add(struct acpi_device *device, + void (*release)(struct device *)) { int result; struct acpi_device_bus_id *acpi_device_bus_id, *new_bus_id; int found = 0; + if (device->handle) { + acpi_status status; + + status = acpi_attach_data(device->handle, acpi_bus_data_handler, + device); + if (ACPI_FAILURE(status)) { + acpi_handle_err(device->handle, + "Unable to attach device data\n"); + return -ENODEV; + } + } + /* * Linkage * ------- @@ -642,11 +712,13 @@ static int acpi_device_register(struct acpi_device *device) INIT_LIST_HEAD(&device->wakeup_list); INIT_LIST_HEAD(&device->physical_node_list); mutex_init(&device->physical_node_lock); + INIT_LIST_HEAD(&device->power_dependent); new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL); if (!new_bus_id) { - printk(KERN_ERR PREFIX "Memory allocation error\n"); - return -ENOMEM; + pr_err(PREFIX "Memory allocation error\n"); + result = -ENOMEM; + goto err_detach; } mutex_lock(&acpi_device_lock); @@ -681,11 +753,11 @@ static int acpi_device_register(struct acpi_device *device) if (device->parent) device->dev.parent = &device->parent->dev; device->dev.bus = &acpi_bus_type; - device->dev.release = &acpi_device_release; - result = device_register(&device->dev); + device->dev.release = release; + result = device_add(&device->dev); if (result) { dev_err(&device->dev, "Error registering device\n"); - goto end; + goto err; } result = acpi_device_setup_files(device); @@ -695,16 +767,20 @@ static int acpi_device_register(struct acpi_device *device) device->removal_type = ACPI_BUS_REMOVAL_NORMAL; return 0; -end: + + err: mutex_lock(&acpi_device_lock); if (device->parent) list_del(&device->node); list_del(&device->wakeup_list); mutex_unlock(&acpi_device_lock); + + err_detach: + acpi_detach_data(device->handle, acpi_bus_data_handler); return result; } -static void acpi_device_unregister(struct acpi_device *device, int type) +static void acpi_device_unregister(struct acpi_device *device) { mutex_lock(&acpi_device_lock); if (device->parent) @@ -715,8 +791,20 @@ static void acpi_device_unregister(struct acpi_device *device, int type) acpi_detach_data(device->handle, acpi_bus_data_handler); + acpi_power_add_remove_device(device, false); acpi_device_remove_files(device); - device_unregister(&device->dev); + if (device->remove) + device->remove(device); + + device_del(&device->dev); + /* + * Transition the device to D3cold to drop the reference counts of all + * power resources the device depends on and turn off the ones that have + * no more references. + */ + acpi_device_set_power(device, ACPI_STATE_D3_COLD); + device->handle = NULL; + put_device(&device->dev); } /* -------------------------------------------------------------------------- @@ -760,24 +848,6 @@ acpi_bus_driver_init(struct acpi_device *device, struct acpi_driver *driver) return 0; } -static int acpi_start_single_object(struct acpi_device *device) -{ - int result = 0; - struct acpi_driver *driver; - - - if (!(driver = device->driver)) - return 0; - - if (driver->ops.start) { - result = driver->ops.start(device); - if (result && driver->ops.remove) - driver->ops.remove(device, ACPI_BUS_REMOVAL_NORMAL); - } - - return result; -} - /** * acpi_bus_register_driver - register a driver with the ACPI bus * @driver: driver being registered @@ -821,29 +891,23 @@ EXPORT_SYMBOL(acpi_bus_unregister_driver); -------------------------------------------------------------------------- */ static struct acpi_device *acpi_bus_get_parent(acpi_handle handle) { + struct acpi_device *device = NULL; acpi_status status; - int ret; - struct acpi_device *device; /* * Fixed hardware devices do not appear in the namespace and do not * have handles, but we fabricate acpi_devices for them, so we have * to deal with them specially. */ - if (handle == NULL) + if (!handle) return acpi_root; do { status = acpi_get_parent(handle, &handle); - if (status == AE_NULL_ENTRY) - return NULL; if (ACPI_FAILURE(status)) - return acpi_root; - - ret = acpi_bus_get_device(handle, &device); - if (ret == 0) - return device; - } while (1); + return status == AE_NULL_ENTRY ? NULL : acpi_root; + } while (acpi_bus_get_device(handle, &device)); + return device; } acpi_status @@ -877,52 +941,43 @@ void acpi_bus_data_handler(acpi_handle handle, void *context) return; } -static int acpi_bus_get_perf_flags(struct acpi_device *device) -{ - device->performance.state = ACPI_STATE_UNKNOWN; - return 0; -} - -static acpi_status -acpi_bus_extract_wakeup_device_power_package(acpi_handle handle, - struct acpi_device_wakeup *wakeup) +static int acpi_bus_extract_wakeup_device_power_package(acpi_handle handle, + struct acpi_device_wakeup *wakeup) { struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *package = NULL; union acpi_object *element = NULL; acpi_status status; - int i = 0; + int err = -ENODATA; if (!wakeup) - return AE_BAD_PARAMETER; + return -EINVAL; + + INIT_LIST_HEAD(&wakeup->resources); /* _PRW */ status = acpi_evaluate_object(handle, "_PRW", NULL, &buffer); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PRW")); - return status; + return err; } package = (union acpi_object *)buffer.pointer; - if (!package || (package->package.count < 2)) { - status = AE_BAD_DATA; + if (!package || package->package.count < 2) goto out; - } element = &(package->package.elements[0]); - if (!element) { - status = AE_BAD_DATA; + if (!element) goto out; - } + if (element->type == ACPI_TYPE_PACKAGE) { if ((element->package.count < 2) || (element->package.elements[0].type != ACPI_TYPE_LOCAL_REFERENCE) - || (element->package.elements[1].type != ACPI_TYPE_INTEGER)) { - status = AE_BAD_DATA; + || (element->package.elements[1].type != ACPI_TYPE_INTEGER)) goto out; - } + wakeup->gpe_device = element->package.elements[0].reference.handle; wakeup->gpe_number = @@ -931,38 +986,35 @@ acpi_bus_extract_wakeup_device_power_package(acpi_handle handle, wakeup->gpe_device = NULL; wakeup->gpe_number = element->integer.value; } else { - status = AE_BAD_DATA; goto out; } element = &(package->package.elements[1]); - if (element->type != ACPI_TYPE_INTEGER) { - status = AE_BAD_DATA; + if (element->type != ACPI_TYPE_INTEGER) goto out; - } + wakeup->sleep_state = element->integer.value; - if ((package->package.count - 2) > ACPI_MAX_HANDLES) { - status = AE_NO_MEMORY; + err = acpi_extract_power_resources(package, 2, &wakeup->resources); + if (err) goto out; - } - wakeup->resources.count = package->package.count - 2; - for (i = 0; i < wakeup->resources.count; i++) { - element = &(package->package.elements[i + 2]); - if (element->type != ACPI_TYPE_LOCAL_REFERENCE) { - status = AE_BAD_DATA; - goto out; - } - wakeup->resources.handles[i] = element->reference.handle; - } + if (!list_empty(&wakeup->resources)) { + int sleep_state; + sleep_state = acpi_power_min_system_level(&wakeup->resources); + if (sleep_state < wakeup->sleep_state) { + acpi_handle_warn(handle, "Overriding _PRW sleep state " + "(S%d) by S%d from power resources\n", + (int)wakeup->sleep_state, sleep_state); + wakeup->sleep_state = sleep_state; + } + } acpi_setup_gpe_for_wake(handle, wakeup->gpe_device, wakeup->gpe_number); out: kfree(buffer.pointer); - - return status; + return err; } static void acpi_bus_set_run_wake_flags(struct acpi_device *device) @@ -1002,17 +1054,17 @@ static void acpi_bus_get_wakeup_device_flags(struct acpi_device *device) { acpi_handle temp; acpi_status status = 0; - int psw_error; + int err; /* Presence of _PRW indicates wake capable */ status = acpi_get_handle(device->handle, "_PRW", &temp); if (ACPI_FAILURE(status)) return; - status = acpi_bus_extract_wakeup_device_power_package(device->handle, - &device->wakeup); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Extracting _PRW package")); + err = acpi_bus_extract_wakeup_device_power_package(device->handle, + &device->wakeup); + if (err) { + dev_err(&device->dev, "_PRW evaluation error: %d\n", err); return; } @@ -1025,20 +1077,73 @@ static void acpi_bus_get_wakeup_device_flags(struct acpi_device *device) * So it is necessary to call _DSW object first. Only when it is not * present will the _PSW object used. */ - psw_error = acpi_device_sleep_wake(device, 0, 0, 0); - if (psw_error) + err = acpi_device_sleep_wake(device, 0, 0, 0); + if (err) ACPI_DEBUG_PRINT((ACPI_DB_INFO, "error in _DSW or _PSW evaluation\n")); } -static void acpi_bus_add_power_resource(acpi_handle handle); +static void acpi_bus_init_power_state(struct acpi_device *device, int state) +{ + struct acpi_device_power_state *ps = &device->power.states[state]; + char pathname[5] = { '_', 'P', 'R', '0' + state, '\0' }; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + acpi_handle handle; + acpi_status status; + + INIT_LIST_HEAD(&ps->resources); + + /* Evaluate "_PRx" to get referenced power resources */ + status = acpi_evaluate_object(device->handle, pathname, NULL, &buffer); + if (ACPI_SUCCESS(status)) { + union acpi_object *package = buffer.pointer; + + if (buffer.length && package + && package->type == ACPI_TYPE_PACKAGE + && package->package.count) { + int err = acpi_extract_power_resources(package, 0, + &ps->resources); + if (!err) + device->power.flags.power_resources = 1; + } + ACPI_FREE(buffer.pointer); + } + + /* Evaluate "_PSx" to see if we can do explicit sets */ + pathname[2] = 'S'; + status = acpi_get_handle(device->handle, pathname, &handle); + if (ACPI_SUCCESS(status)) + ps->flags.explicit_set = 1; + + /* + * State is valid if there are means to put the device into it. + * D3hot is only valid if _PR3 present. + */ + if (!list_empty(&ps->resources) + || (ps->flags.explicit_set && state < ACPI_STATE_D3_HOT)) { + ps->flags.valid = 1; + ps->flags.os_accessible = 1; + } + + ps->power = -1; /* Unknown - driver assigned */ + ps->latency = -1; /* Unknown - driver assigned */ +} -static int acpi_bus_get_power_flags(struct acpi_device *device) +static void acpi_bus_get_power_flags(struct acpi_device *device) { - acpi_status status = 0; - acpi_handle handle = NULL; - u32 i = 0; + acpi_status status; + acpi_handle handle; + u32 i; + + /* Presence of _PS0|_PR0 indicates 'power manageable' */ + status = acpi_get_handle(device->handle, "_PS0", &handle); + if (ACPI_FAILURE(status)) { + status = acpi_get_handle(device->handle, "_PR0", &handle); + if (ACPI_FAILURE(status)) + return; + } + device->flags.power_manageable = 1; /* * Power Management Flags @@ -1053,40 +1158,10 @@ static int acpi_bus_get_power_flags(struct acpi_device *device) /* * Enumerate supported power management states */ - for (i = ACPI_STATE_D0; i <= ACPI_STATE_D3_HOT; i++) { - struct acpi_device_power_state *ps = &device->power.states[i]; - char object_name[5] = { '_', 'P', 'R', '0' + i, '\0' }; - - /* Evaluate "_PRx" to se if power resources are referenced */ - acpi_evaluate_reference(device->handle, object_name, NULL, - &ps->resources); - if (ps->resources.count) { - int j; - - device->power.flags.power_resources = 1; - for (j = 0; j < ps->resources.count; j++) - acpi_bus_add_power_resource(ps->resources.handles[j]); - } + for (i = ACPI_STATE_D0; i <= ACPI_STATE_D3_HOT; i++) + acpi_bus_init_power_state(device, i); - /* Evaluate "_PSx" to see if we can do explicit sets */ - object_name[2] = 'S'; - status = acpi_get_handle(device->handle, object_name, &handle); - if (ACPI_SUCCESS(status)) - ps->flags.explicit_set = 1; - - /* - * State is valid if there are means to put the device into it. - * D3hot is only valid if _PR3 present. - */ - if (ps->resources.count || - (ps->flags.explicit_set && i < ACPI_STATE_D3_HOT)) { - ps->flags.valid = 1; - ps->flags.os_accessible = 1; - } - - ps->power = -1; /* Unknown - driver assigned */ - ps->latency = -1; /* Unknown - driver assigned */ - } + INIT_LIST_HEAD(&device->power.states[ACPI_STATE_D3_COLD].resources); /* Set defaults for D0 and D3 states (always valid) */ device->power.states[ACPI_STATE_D0].flags.valid = 1; @@ -1103,17 +1178,17 @@ static int acpi_bus_get_power_flags(struct acpi_device *device) device->power.flags.power_resources) device->power.states[ACPI_STATE_D3_COLD].flags.os_accessible = 1; - acpi_bus_init_power(device); - - return 0; + if (acpi_bus_init_power(device)) { + acpi_free_power_resources_lists(device); + device->flags.power_manageable = 0; + } } -static int acpi_bus_get_flags(struct acpi_device *device) +static void acpi_bus_get_flags(struct acpi_device *device) { acpi_status status = AE_OK; acpi_handle temp = NULL; - /* Presence of _STA indicates 'dynamic_status' */ status = acpi_get_handle(device->handle, "_STA", &temp); if (ACPI_SUCCESS(status)) @@ -1133,21 +1208,6 @@ static int acpi_bus_get_flags(struct acpi_device *device) if (ACPI_SUCCESS(status)) device->flags.ejectable = 1; } - - /* Power resources cannot be power manageable. */ - if (device->device_type == ACPI_BUS_TYPE_POWER) - return 0; - - /* Presence of _PS0|_PR0 indicates 'power manageable' */ - status = acpi_get_handle(device->handle, "_PS0", &temp); - if (ACPI_FAILURE(status)) - status = acpi_get_handle(device->handle, "_PR0", &temp); - if (ACPI_SUCCESS(status)) - device->flags.power_manageable = 1; - - /* TBD: Performance management */ - - return 0; } static void acpi_device_get_busid(struct acpi_device *device) @@ -1372,56 +1432,32 @@ static void acpi_device_set_id(struct acpi_device *device) } } -static int acpi_device_set_context(struct acpi_device *device) +void acpi_init_device_object(struct acpi_device *device, acpi_handle handle, + int type, unsigned long long sta) { - acpi_status status; - - /* - * Context - * ------- - * Attach this 'struct acpi_device' to the ACPI object. This makes - * resolutions from handle->device very efficient. Fixed hardware - * devices have no handles, so we skip them. - */ - if (!device->handle) - return 0; - - status = acpi_attach_data(device->handle, - acpi_bus_data_handler, device); - if (ACPI_SUCCESS(status)) - return 0; - - printk(KERN_ERR PREFIX "Error attaching device data\n"); - return -ENODEV; + INIT_LIST_HEAD(&device->pnp.ids); + device->device_type = type; + device->handle = handle; + device->parent = acpi_bus_get_parent(handle); + STRUCT_TO_INT(device->status) = sta; + acpi_device_get_busid(device); + acpi_device_set_id(device); + acpi_bus_get_flags(device); + device->flags.match_driver = false; + device_initialize(&device->dev); + dev_set_uevent_suppress(&device->dev, true); } -static int acpi_bus_remove(struct acpi_device *dev, int rmdevice) +void acpi_device_add_finalize(struct acpi_device *device) { - if (!dev) - return -EINVAL; - - dev->removal_type = ACPI_BUS_REMOVAL_EJECT; - device_release_driver(&dev->dev); - - if (!rmdevice) - return 0; - - /* - * unbind _ADR-Based Devices when hot removal - */ - if (dev->flags.bus_address) { - if ((dev->parent) && (dev->parent->ops.unbind)) - dev->parent->ops.unbind(dev); - } - acpi_device_unregister(dev, ACPI_BUS_REMOVAL_EJECT); - - return 0; + device->flags.match_driver = true; + dev_set_uevent_suppress(&device->dev, false); + kobject_uevent(&device->dev.kobj, KOBJ_ADD); } static int acpi_add_single_object(struct acpi_device **child, acpi_handle handle, int type, - unsigned long long sta, - struct acpi_bus_ops *ops) + unsigned long long sta) { int result; struct acpi_device *device; @@ -1433,102 +1469,25 @@ static int acpi_add_single_object(struct acpi_device **child, return -ENOMEM; } - INIT_LIST_HEAD(&device->pnp.ids); - device->device_type = type; - device->handle = handle; - device->parent = acpi_bus_get_parent(handle); - device->bus_ops = *ops; /* workround for not call .start */ - STRUCT_TO_INT(device->status) = sta; - - acpi_device_get_busid(device); - - /* - * Flags - * ----- - * Note that we only look for object handles -- cannot evaluate objects - * until we know the device is present and properly initialized. - */ - result = acpi_bus_get_flags(device); - if (result) - goto end; - - /* - * Initialize Device - * ----------------- - * TBD: Synch with Core's enumeration/initialization process. - */ - acpi_device_set_id(device); - - /* - * Power Management - * ---------------- - */ - if (device->flags.power_manageable) { - result = acpi_bus_get_power_flags(device); - if (result) - goto end; - } - - /* - * Wakeup device management - *----------------------- - */ + acpi_init_device_object(device, handle, type, sta); + acpi_bus_get_power_flags(device); acpi_bus_get_wakeup_device_flags(device); - /* - * Performance Management - * ---------------------- - */ - if (device->flags.performance_manageable) { - result = acpi_bus_get_perf_flags(device); - if (result) - goto end; - } - - if ((result = acpi_device_set_context(device))) - goto end; - - result = acpi_device_register(device); - - /* - * Bind _ADR-Based Devices when hot add - */ - if (device->flags.bus_address) { - if (device->parent && device->parent->ops.bind) - device->parent->ops.bind(device); - } - -end: - if (!result) { - acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Adding %s [%s] parent %s\n", dev_name(&device->dev), - (char *) buffer.pointer, - device->parent ? dev_name(&device->parent->dev) : - "(null)")); - kfree(buffer.pointer); - *child = device; - } else + result = acpi_device_add(device, acpi_device_release); + if (result) { acpi_device_release(&device->dev); + return result; + } - return result; -} - -#define ACPI_STA_DEFAULT (ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED | \ - ACPI_STA_DEVICE_UI | ACPI_STA_DEVICE_FUNCTIONING) - -static void acpi_bus_add_power_resource(acpi_handle handle) -{ - struct acpi_bus_ops ops = { - .acpi_op_add = 1, - .acpi_op_start = 1, - }; - struct acpi_device *device = NULL; - - acpi_bus_get_device(handle, &device); - if (!device) - acpi_add_single_object(&device, handle, ACPI_BUS_TYPE_POWER, - ACPI_STA_DEFAULT, &ops); + acpi_power_add_remove_device(device, true); + acpi_device_add_finalize(device); + acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Added %s [%s] parent %s\n", + dev_name(&device->dev), (char *) buffer.pointer, + device->parent ? dev_name(&device->parent->dev) : "(null)")); + kfree(buffer.pointer); + *child = device; + return 0; } static int acpi_bus_type_and_status(acpi_handle handle, int *type, @@ -1570,218 +1529,248 @@ static int acpi_bus_type_and_status(acpi_handle handle, int *type, return 0; } -static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl, - void *context, void **return_value) +static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, + void *not_used, void **return_value) { - struct acpi_bus_ops *ops = context; + struct acpi_device *device = NULL; int type; unsigned long long sta; - struct acpi_device *device; acpi_status status; int result; + acpi_bus_get_device(handle, &device); + if (device) + goto out; + result = acpi_bus_type_and_status(handle, &type, &sta); if (result) return AE_OK; + if (type == ACPI_BUS_TYPE_POWER) { + acpi_add_power_resource(handle); + return AE_OK; + } + if (!(sta & ACPI_STA_DEVICE_PRESENT) && !(sta & ACPI_STA_DEVICE_FUNCTIONING)) { struct acpi_device_wakeup wakeup; acpi_handle temp; status = acpi_get_handle(handle, "_PRW", &temp); - if (ACPI_SUCCESS(status)) + if (ACPI_SUCCESS(status)) { acpi_bus_extract_wakeup_device_power_package(handle, &wakeup); + acpi_power_resources_list_free(&wakeup.resources); + } return AE_CTRL_DEPTH; } - /* - * We may already have an acpi_device from a previous enumeration. If - * so, we needn't add it again, but we may still have to start it. - */ - device = NULL; - acpi_bus_get_device(handle, &device); - if (ops->acpi_op_add && !device) { - acpi_add_single_object(&device, handle, type, sta, ops); - /* Is the device a known good platform device? */ - if (device - && !acpi_match_device_ids(device, acpi_platform_device_ids)) - acpi_create_platform_device(device); - } - + acpi_add_single_object(&device, handle, type, sta); if (!device) return AE_CTRL_DEPTH; - if (ops->acpi_op_start && !(ops->acpi_op_add)) { - status = acpi_start_single_object(device); - if (ACPI_FAILURE(status)) - return AE_CTRL_DEPTH; - } - + out: if (!*return_value) *return_value = device; + return AE_OK; } -static int acpi_bus_scan(acpi_handle handle, struct acpi_bus_ops *ops, - struct acpi_device **child) +static int acpi_scan_do_attach_handler(struct acpi_device *device, char *id) { - acpi_status status; - void *device = NULL; + struct acpi_scan_handler *handler; - status = acpi_bus_check_add(handle, 0, ops, &device); - if (ACPI_SUCCESS(status)) - acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, - acpi_bus_check_add, NULL, ops, &device); + list_for_each_entry(handler, &acpi_scan_handlers_list, list_node) { + const struct acpi_device_id *devid; - if (child) - *child = device; + for (devid = handler->ids; devid->id[0]; devid++) { + int ret; - if (device) - return 0; - else - return -ENODEV; -} + if (strcmp((char *)devid->id, id)) + continue; -/* - * acpi_bus_add and acpi_bus_start - * - * scan a given ACPI tree and (probably recently hot-plugged) - * create and add or starts found devices. - * - * If no devices were found -ENODEV is returned which does not - * mean that this is a real error, there just have been no suitable - * ACPI objects in the table trunk from which the kernel could create - * a device and add/start an appropriate driver. - */ + ret = handler->attach(device, devid); + if (ret > 0) { + device->handler = handler; + return ret; + } else if (ret < 0) { + return ret; + } + } + } + return 0; +} -int -acpi_bus_add(struct acpi_device **child, - struct acpi_device *parent, acpi_handle handle, int type) +static int acpi_scan_attach_handler(struct acpi_device *device) { - struct acpi_bus_ops ops; + struct acpi_hardware_id *hwid; + int ret = 0; - memset(&ops, 0, sizeof(ops)); - ops.acpi_op_add = 1; + list_for_each_entry(hwid, &device->pnp.ids, list) { + ret = acpi_scan_do_attach_handler(device, hwid->id); + if (ret) + break; - return acpi_bus_scan(handle, &ops, child); + } + return ret; } -EXPORT_SYMBOL(acpi_bus_add); -int acpi_bus_start(struct acpi_device *device) +static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used, + void *not_used, void **ret_not_used) { - struct acpi_bus_ops ops; - int result; - - if (!device) - return -EINVAL; + struct acpi_device *device; + unsigned long long sta_not_used; + int ret; - memset(&ops, 0, sizeof(ops)); - ops.acpi_op_start = 1; + /* + * Ignore errors ignored by acpi_bus_check_add() to avoid terminating + * namespace walks prematurely. + */ + if (acpi_bus_type_and_status(handle, &ret, &sta_not_used)) + return AE_OK; - result = acpi_bus_scan(device->handle, &ops, NULL); + if (acpi_bus_get_device(handle, &device)) + return AE_CTRL_DEPTH; - acpi_update_all_gpes(); + ret = acpi_scan_attach_handler(device); + if (ret) + return ret > 0 ? AE_OK : AE_CTRL_DEPTH; - return result; + ret = device_attach(&device->dev); + return ret >= 0 ? AE_OK : AE_CTRL_DEPTH; } -EXPORT_SYMBOL(acpi_bus_start); -int acpi_bus_trim(struct acpi_device *start, int rmdevice) +/** + * acpi_bus_scan - Add ACPI device node objects in a given namespace scope. + * @handle: Root of the namespace scope to scan. + * + * Scan a given ACPI tree (probably recently hot-plugged) and create and add + * found devices. + * + * If no devices were found, -ENODEV is returned, but it does not mean that + * there has been a real error. There just have been no suitable ACPI objects + * in the table trunk from which the kernel could create a device and add an + * appropriate driver. + * + * Must be called under acpi_scan_lock. + */ +int acpi_bus_scan(acpi_handle handle) { - acpi_status status; - struct acpi_device *parent, *child; - acpi_handle phandle, chandle; - acpi_object_type type; - u32 level = 1; - int err = 0; + void *device = NULL; + int error = 0; - parent = start; - phandle = start->handle; - child = chandle = NULL; + if (ACPI_SUCCESS(acpi_bus_check_add(handle, 0, NULL, &device))) + acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, + acpi_bus_check_add, NULL, NULL, &device); - while ((level > 0) && parent && (!err)) { - status = acpi_get_next_object(ACPI_TYPE_ANY, phandle, - chandle, &chandle); + if (!device) + error = -ENODEV; + else if (ACPI_SUCCESS(acpi_bus_device_attach(handle, 0, NULL, NULL))) + acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, + acpi_bus_device_attach, NULL, NULL, NULL); - /* - * If this scope is exhausted then move our way back up. - */ - if (ACPI_FAILURE(status)) { - level--; - chandle = phandle; - acpi_get_parent(phandle, &phandle); - child = parent; - parent = parent->parent; - - if (level == 0) - err = acpi_bus_remove(child, rmdevice); - else - err = acpi_bus_remove(child, 1); + return error; +} +EXPORT_SYMBOL(acpi_bus_scan); - continue; - } +static acpi_status acpi_bus_device_detach(acpi_handle handle, u32 lvl_not_used, + void *not_used, void **ret_not_used) +{ + struct acpi_device *device = NULL; - status = acpi_get_type(chandle, &type); - if (ACPI_FAILURE(status)) { - continue; - } - /* - * If there is a device corresponding to chandle then - * parse it (depth-first). - */ - if (acpi_bus_get_device(chandle, &child) == 0) { - level++; - phandle = chandle; - chandle = NULL; - parent = child; + if (!acpi_bus_get_device(handle, &device)) { + struct acpi_scan_handler *dev_handler = device->handler; + + device->removal_type = ACPI_BUS_REMOVAL_EJECT; + if (dev_handler) { + if (dev_handler->detach) + dev_handler->detach(device); + + device->handler = NULL; + } else { + device_release_driver(&device->dev); } - continue; } - return err; + return AE_OK; +} + +static acpi_status acpi_bus_remove(acpi_handle handle, u32 lvl_not_used, + void *not_used, void **ret_not_used) +{ + struct acpi_device *device = NULL; + + if (!acpi_bus_get_device(handle, &device)) + acpi_device_unregister(device); + + return AE_OK; +} + +/** + * acpi_bus_trim - Remove ACPI device node and all of its descendants + * @start: Root of the ACPI device nodes subtree to remove. + * + * Must be called under acpi_scan_lock. + */ +void acpi_bus_trim(struct acpi_device *start) +{ + /* + * Execute acpi_bus_device_detach() as a post-order callback to detach + * all ACPI drivers from the device nodes being removed. + */ + acpi_walk_namespace(ACPI_TYPE_ANY, start->handle, ACPI_UINT32_MAX, NULL, + acpi_bus_device_detach, NULL, NULL); + acpi_bus_device_detach(start->handle, 0, NULL, NULL); + /* + * Execute acpi_bus_remove() as a post-order callback to remove device + * nodes in the given namespace scope. + */ + acpi_walk_namespace(ACPI_TYPE_ANY, start->handle, ACPI_UINT32_MAX, NULL, + acpi_bus_remove, NULL, NULL); + acpi_bus_remove(start->handle, 0, NULL, NULL); } EXPORT_SYMBOL_GPL(acpi_bus_trim); static int acpi_bus_scan_fixed(void) { int result = 0; - struct acpi_device *device = NULL; - struct acpi_bus_ops ops; - - memset(&ops, 0, sizeof(ops)); - ops.acpi_op_add = 1; - ops.acpi_op_start = 1; /* * Enumerate all fixed-feature devices. */ - if ((acpi_gbl_FADT.flags & ACPI_FADT_POWER_BUTTON) == 0) { + if (!(acpi_gbl_FADT.flags & ACPI_FADT_POWER_BUTTON)) { + struct acpi_device *device = NULL; + result = acpi_add_single_object(&device, NULL, ACPI_BUS_TYPE_POWER_BUTTON, - ACPI_STA_DEFAULT, - &ops); + ACPI_STA_DEFAULT); + if (result) + return result; + + result = device_attach(&device->dev); + if (result < 0) + return result; + device_init_wakeup(&device->dev, true); } - if ((acpi_gbl_FADT.flags & ACPI_FADT_SLEEP_BUTTON) == 0) { + if (!(acpi_gbl_FADT.flags & ACPI_FADT_SLEEP_BUTTON)) { + struct acpi_device *device = NULL; + result = acpi_add_single_object(&device, NULL, ACPI_BUS_TYPE_SLEEP_BUTTON, - ACPI_STA_DEFAULT, - &ops); + ACPI_STA_DEFAULT); + if (result) + return result; + + result = device_attach(&device->dev); } - return result; + return result < 0 ? result : 0; } int __init acpi_scan_init(void) { int result; - struct acpi_bus_ops ops; - - memset(&ops, 0, sizeof(ops)); - ops.acpi_op_add = 1; - ops.acpi_op_start = 1; result = bus_register(&acpi_bus_type); if (result) { @@ -1789,20 +1778,33 @@ int __init acpi_scan_init(void) printk(KERN_ERR PREFIX "Could not register bus type\n"); } - acpi_power_init(); + acpi_pci_root_init(); + acpi_pci_link_init(); + acpi_platform_init(); + acpi_csrt_init(); + acpi_container_init(); + mutex_lock(&acpi_scan_lock); /* * Enumerate devices in the ACPI namespace. */ - result = acpi_bus_scan(ACPI_ROOT_OBJECT, &ops, &acpi_root); - - if (!result) - result = acpi_bus_scan_fixed(); + result = acpi_bus_scan(ACPI_ROOT_OBJECT); + if (result) + goto out; + result = acpi_bus_get_device(ACPI_ROOT_OBJECT, &acpi_root); if (result) - acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL); - else - acpi_update_all_gpes(); + goto out; + + result = acpi_bus_scan_fixed(); + if (result) { + acpi_device_unregister(acpi_root); + goto out; + } + acpi_update_all_gpes(); + + out: + mutex_unlock(&acpi_scan_lock); return result; } diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 2fcc67d34b117347d873f36b119d5cf9585fe889..6d3a06a629a1f8e1627f1218d88053cf7857053d 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -177,6 +177,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { }, { .callback = init_nvs_nosave, + .ident = "Sony Vaio VGN-FW41E_H", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW41E_H"), + }, + }, + { + .callback = init_nvs_nosave, .ident = "Sony Vaio VGN-FW21E", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), @@ -386,6 +394,8 @@ static void acpi_pm_finish(void) acpi_target_sleep_state = ACPI_STATE_S0; + acpi_resume_power_resources(); + /* If we were woken with the fixed power button, provide a small * hint to userspace in the form of a wakeup event on the fixed power * button device (if it can be found). @@ -577,7 +587,28 @@ static const struct platform_suspend_ops acpi_suspend_ops_old = { .end = acpi_pm_end, .recover = acpi_pm_finish, }; -#endif /* CONFIG_SUSPEND */ + +static void acpi_sleep_suspend_setup(void) +{ + int i; + + for (i = ACPI_STATE_S1; i < ACPI_STATE_S4; i++) { + acpi_status status; + u8 type_a, type_b; + + status = acpi_get_sleep_type_data(i, &type_a, &type_b); + if (ACPI_SUCCESS(status)) { + sleep_states[i] = 1; + pr_cont(" S%d", i); + } + } + + suspend_set_ops(old_suspend_ordering ? + &acpi_suspend_ops_old : &acpi_suspend_ops); +} +#else /* !CONFIG_SUSPEND */ +static inline void acpi_sleep_suspend_setup(void) {} +#endif /* !CONFIG_SUSPEND */ #ifdef CONFIG_HIBERNATION static unsigned long s4_hardware_signature; @@ -698,7 +729,30 @@ static const struct platform_hibernation_ops acpi_hibernation_ops_old = { .restore_cleanup = acpi_pm_thaw, .recover = acpi_pm_finish, }; -#endif /* CONFIG_HIBERNATION */ + +static void acpi_sleep_hibernate_setup(void) +{ + acpi_status status; + u8 type_a, type_b; + + status = acpi_get_sleep_type_data(ACPI_STATE_S4, &type_a, &type_b); + if (ACPI_FAILURE(status)) + return; + + hibernation_set_ops(old_suspend_ordering ? + &acpi_hibernation_ops_old : &acpi_hibernation_ops); + sleep_states[ACPI_STATE_S4] = 1; + pr_cont(KERN_CONT " S4"); + if (nosigcheck) + return; + + acpi_get_table(ACPI_SIG_FACS, 1, (struct acpi_table_header **)&facs); + if (facs) + s4_hardware_signature = facs->hardware_signature; +} +#else /* !CONFIG_HIBERNATION */ +static inline void acpi_sleep_hibernate_setup(void) {} +#endif /* !CONFIG_HIBERNATION */ int acpi_suspend(u32 acpi_state) { @@ -734,9 +788,6 @@ int __init acpi_sleep_init(void) { acpi_status status; u8 type_a, type_b; -#ifdef CONFIG_SUSPEND - int i = 0; -#endif if (acpi_disabled) return 0; @@ -744,45 +795,19 @@ int __init acpi_sleep_init(void) acpi_sleep_dmi_check(); sleep_states[ACPI_STATE_S0] = 1; - printk(KERN_INFO PREFIX "(supports S0"); - -#ifdef CONFIG_SUSPEND - for (i = ACPI_STATE_S1; i < ACPI_STATE_S4; i++) { - status = acpi_get_sleep_type_data(i, &type_a, &type_b); - if (ACPI_SUCCESS(status)) { - sleep_states[i] = 1; - printk(KERN_CONT " S%d", i); - } - } + pr_info(PREFIX "(supports S0"); - suspend_set_ops(old_suspend_ordering ? - &acpi_suspend_ops_old : &acpi_suspend_ops); -#endif + acpi_sleep_suspend_setup(); + acpi_sleep_hibernate_setup(); -#ifdef CONFIG_HIBERNATION - status = acpi_get_sleep_type_data(ACPI_STATE_S4, &type_a, &type_b); - if (ACPI_SUCCESS(status)) { - hibernation_set_ops(old_suspend_ordering ? - &acpi_hibernation_ops_old : &acpi_hibernation_ops); - sleep_states[ACPI_STATE_S4] = 1; - printk(KERN_CONT " S4"); - if (!nosigcheck) { - acpi_get_table(ACPI_SIG_FACS, 1, - (struct acpi_table_header **)&facs); - if (facs) - s4_hardware_signature = - facs->hardware_signature; - } - } -#endif status = acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b); if (ACPI_SUCCESS(status)) { sleep_states[ACPI_STATE_S5] = 1; - printk(KERN_CONT " S5"); + pr_cont(" S5"); pm_power_off_prepare = acpi_power_off_prepare; pm_power_off = acpi_power_off; } - printk(KERN_CONT ")\n"); + pr_cont(")\n"); /* * Register the tts_notifier to reboot notifier list so that the _TTS * object can also be evaluated when the system enters S5. diff --git a/drivers/acpi/sleep.h b/drivers/acpi/sleep.h index 74d59c8f4678a385ccd575816c6f7ad1e1727456..0143540a251979a4dd0ad1b21cce60d7cf47e815 100644 --- a/drivers/acpi/sleep.h +++ b/drivers/acpi/sleep.h @@ -6,3 +6,5 @@ extern void acpi_disable_wakeup_devices(u8 sleep_state); extern struct list_head acpi_wakeup_device_list; extern struct mutex acpi_device_lock; + +extern void acpi_resume_power_resources(void); diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c index ea61ca9129cdfe6322b7677a27d6c5a52c110192..41c0504470dbc8a09ebf79ae044963c70dface82 100644 --- a/drivers/acpi/sysfs.c +++ b/drivers/acpi/sysfs.c @@ -498,7 +498,7 @@ static int get_status(u32 index, acpi_event_status *status, result = acpi_get_gpe_device(index, handle); if (result) { ACPI_EXCEPTION((AE_INFO, AE_NOT_FOUND, - "Invalid GPE 0x%x\n", index)); + "Invalid GPE 0x%x", index)); goto end; } result = acpi_get_gpe_status(*handle, index, status); diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index 2572d9715bda3b14ff3f43cb0efaf3122d26b26d..d67a1fe07f0ed60fc8f6aef61bde04bbbcb84e76 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -204,7 +204,7 @@ int __init acpi_table_parse_entries(char *id, unsigned long table_size, int entry_id, - acpi_table_entry_handler handler, + acpi_tbl_entry_handler handler, unsigned int max_entries) { struct acpi_table_header *table_header = NULL; @@ -269,7 +269,7 @@ acpi_table_parse_entries(char *id, int __init acpi_table_parse_madt(enum acpi_madt_type id, - acpi_table_entry_handler handler, unsigned int max_entries) + acpi_tbl_entry_handler handler, unsigned int max_entries) { return acpi_table_parse_entries(ACPI_SIG_MADT, sizeof(struct acpi_table_madt), id, @@ -285,7 +285,7 @@ acpi_table_parse_madt(enum acpi_madt_type id, * Scan the ACPI System Descriptor Table (STD) for a table matching @id, * run @handler on it. Return 0 if table found, return on if not. */ -int __init acpi_table_parse(char *id, acpi_table_handler handler) +int __init acpi_table_parse(char *id, acpi_tbl_table_handler handler) { struct acpi_table_header *table = NULL; acpi_size tbl_size; diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 506fbd4b5733b5f1751d8c23521aaa398447e33d..8470771e5eae1a2c69bc9df34c70c09138403128 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -97,7 +97,7 @@ module_param(psv, int, 0644); MODULE_PARM_DESC(psv, "Disable or override all passive trip points."); static int acpi_thermal_add(struct acpi_device *device); -static int acpi_thermal_remove(struct acpi_device *device, int type); +static int acpi_thermal_remove(struct acpi_device *device); static void acpi_thermal_notify(struct acpi_device *device, u32 event); static const struct acpi_device_id thermal_device_ids[] = { @@ -288,7 +288,7 @@ do { \ if (flags != ACPI_TRIPS_INIT) \ ACPI_EXCEPTION((AE_INFO, AE_ERROR, \ "ACPI thermal trip point %s changed\n" \ - "Please send acpidump to linux-acpi@vger.kernel.org\n", str)); \ + "Please send acpidump to linux-acpi@vger.kernel.org", str)); \ } while (0) static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) @@ -531,6 +531,10 @@ static void acpi_thermal_check(void *data) { struct acpi_thermal *tz = data; + if (!tz->tz_enabled) { + pr_warn("thermal zone is disabled \n"); + return; + } thermal_zone_device_update(tz->thermal_zone); } @@ -1111,7 +1115,7 @@ static int acpi_thermal_add(struct acpi_device *device) return result; } -static int acpi_thermal_remove(struct acpi_device *device, int type) +static int acpi_thermal_remove(struct acpi_device *device) { struct acpi_thermal *tz = NULL; diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index ac9a69cd45f5a4082a05c743de6dd58aad369c60..313f959413dc09a89c8a8262957b35081b1e2b0b 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -88,7 +88,7 @@ module_param(use_bios_initial_backlight, bool, 0644); static int register_count = 0; static int acpi_video_bus_add(struct acpi_device *device); -static int acpi_video_bus_remove(struct acpi_device *device, int type); +static int acpi_video_bus_remove(struct acpi_device *device); static void acpi_video_bus_notify(struct acpi_device *device, u32 event); static const struct acpi_device_id video_device_ids[] = { @@ -673,7 +673,7 @@ acpi_video_init_brightness(struct acpi_video_device *device) br->levels[i] = br->levels[i - level_ac_battery]; count += level_ac_battery; } else if (level_ac_battery > 2) - ACPI_ERROR((AE_INFO, "Too many duplicates in _BCL package\n")); + ACPI_ERROR((AE_INFO, "Too many duplicates in _BCL package")); /* Check if the _BCL package is in a reversed order */ if (max_level == br->levels[2]) { @@ -682,7 +682,7 @@ acpi_video_init_brightness(struct acpi_video_device *device) acpi_video_cmp_level, NULL); } else if (max_level != br->levels[count - 1]) ACPI_ERROR((AE_INFO, - "Found unordered _BCL package\n")); + "Found unordered _BCL package")); br->count = count; device->brightness = br; @@ -1740,7 +1740,7 @@ static int acpi_video_bus_add(struct acpi_device *device) return error; } -static int acpi_video_bus_remove(struct acpi_device *device, int type) +static int acpi_video_bus_remove(struct acpi_device *device) { struct acpi_video_bus *video = NULL; diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index ef01ac07502e54625cbf02b7ae7ff11322f5c245..6fc67f7efb224c64d076cf3679bd8878e8d278a1 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c @@ -1029,30 +1029,20 @@ static void ata_acpi_register_power_resource(struct ata_device *dev) { struct scsi_device *sdev = dev->sdev; acpi_handle handle; - struct device *device; handle = ata_dev_acpi_handle(dev); - if (!handle) - return; - - device = &sdev->sdev_gendev; - - acpi_power_resource_register_device(device, handle); + if (handle) + acpi_dev_pm_remove_dependent(handle, &sdev->sdev_gendev); } static void ata_acpi_unregister_power_resource(struct ata_device *dev) { struct scsi_device *sdev = dev->sdev; acpi_handle handle; - struct device *device; handle = ata_dev_acpi_handle(dev); - if (!handle) - return; - - device = &sdev->sdev_gendev; - - acpi_power_resource_unregister_device(device, handle); + if (handle) + acpi_dev_pm_remove_dependent(handle, &sdev->sdev_gendev); } void ata_acpi_bind(struct ata_device *dev) diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index acc3a8ded29d0e45d704f6f3ecef261e70e6a5c2..9a6b05a35603c69f4b6b5e38eed5d62f51ea76ff 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -433,8 +433,7 @@ static bool genpd_abort_poweroff(struct generic_pm_domain *genpd) */ void genpd_queue_power_off_work(struct generic_pm_domain *genpd) { - if (!work_pending(&genpd->power_off_work)) - queue_work(pm_wq, &genpd->power_off_work); + queue_work(pm_wq, &genpd->power_off_work); } /** diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c index 50b2831e027d633d2b9d045c919a0dd70e76f64d..32ee0fc7ea54587241f7f3ac22ffc679e0b371de 100644 --- a/drivers/base/power/opp.c +++ b/drivers/base/power/opp.c @@ -162,7 +162,7 @@ unsigned long opp_get_voltage(struct opp *opp) return v; } -EXPORT_SYMBOL(opp_get_voltage); +EXPORT_SYMBOL_GPL(opp_get_voltage); /** * opp_get_freq() - Gets the frequency corresponding to an available opp @@ -192,7 +192,7 @@ unsigned long opp_get_freq(struct opp *opp) return f; } -EXPORT_SYMBOL(opp_get_freq); +EXPORT_SYMBOL_GPL(opp_get_freq); /** * opp_get_opp_count() - Get number of opps available in the opp list @@ -225,7 +225,7 @@ int opp_get_opp_count(struct device *dev) return count; } -EXPORT_SYMBOL(opp_get_opp_count); +EXPORT_SYMBOL_GPL(opp_get_opp_count); /** * opp_find_freq_exact() - search for an exact frequency @@ -276,7 +276,7 @@ struct opp *opp_find_freq_exact(struct device *dev, unsigned long freq, return opp; } -EXPORT_SYMBOL(opp_find_freq_exact); +EXPORT_SYMBOL_GPL(opp_find_freq_exact); /** * opp_find_freq_ceil() - Search for an rounded ceil freq @@ -323,7 +323,7 @@ struct opp *opp_find_freq_ceil(struct device *dev, unsigned long *freq) return opp; } -EXPORT_SYMBOL(opp_find_freq_ceil); +EXPORT_SYMBOL_GPL(opp_find_freq_ceil); /** * opp_find_freq_floor() - Search for a rounded floor freq @@ -374,7 +374,7 @@ struct opp *opp_find_freq_floor(struct device *dev, unsigned long *freq) return opp; } -EXPORT_SYMBOL(opp_find_freq_floor); +EXPORT_SYMBOL_GPL(opp_find_freq_floor); /** * opp_add() - Add an OPP table from a table definitions @@ -568,7 +568,7 @@ int opp_enable(struct device *dev, unsigned long freq) { return opp_set_availability(dev, freq, true); } -EXPORT_SYMBOL(opp_enable); +EXPORT_SYMBOL_GPL(opp_enable); /** * opp_disable() - Disable a specific OPP @@ -590,7 +590,7 @@ int opp_disable(struct device *dev, unsigned long freq) { return opp_set_availability(dev, freq, false); } -EXPORT_SYMBOL(opp_disable); +EXPORT_SYMBOL_GPL(opp_disable); #ifdef CONFIG_CPU_FREQ /** @@ -661,6 +661,7 @@ int opp_init_cpufreq_table(struct device *dev, return 0; } +EXPORT_SYMBOL_GPL(opp_init_cpufreq_table); /** * opp_free_cpufreq_table() - free the cpufreq table @@ -678,6 +679,7 @@ void opp_free_cpufreq_table(struct device *dev, kfree(*table); *table = NULL; } +EXPORT_SYMBOL_GPL(opp_free_cpufreq_table); #endif /* CONFIG_CPU_FREQ */ /** @@ -738,4 +740,5 @@ int of_init_opp_table(struct device *dev) return 0; } +EXPORT_SYMBOL_GPL(of_init_opp_table); #endif diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c index e6ee5e80e546a1c7895194e529e2e70f5e53ce7f..79715e7fa43e34c9cbf9a4521a657d7bb952f9c6 100644 --- a/drivers/base/power/wakeup.c +++ b/drivers/base/power/wakeup.c @@ -382,6 +382,12 @@ static void wakeup_source_activate(struct wakeup_source *ws) { unsigned int cec; + /* + * active wakeup source should bring the system + * out of PM_SUSPEND_FREEZE state + */ + freeze_wake(); + ws->active = true; ws->active_count++; ws->last_time = ktime_get(); diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index fe6d4be4829600d9c6e44078f95ddb65b84ba957..e3f9a99b8522e41dd2a4005142ea396838f26bbf 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -1041,7 +1041,7 @@ static int hpet_acpi_add(struct acpi_device *device) return hpet_alloc(&data); } -static int hpet_acpi_remove(struct acpi_device *device, int type) +static int hpet_acpi_remove(struct acpi_device *device) { /* XXX need to unregister clocksource, dealloc mem, etc */ return -EINVAL; diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index d780295a147371533e5ad936d8c10e86a85fac57..6386a98e43c1b153242254a8c1f4a125daf7a2ad 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c @@ -1142,7 +1142,7 @@ static int sonypi_acpi_add(struct acpi_device *device) return 0; } -static int sonypi_acpi_remove(struct acpi_device *device, int type) +static int sonypi_acpi_remove(struct acpi_device *device) { sonypi_acpi_device = NULL; return 0; diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 0ad642fbe7946a3e4c96ae8a6694d0d73b97b935..14fde73ea6ff9f662fe11999f6b0d01632c5f7e9 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_MACH_LOONGSON1) += clk-ls1x.o obj-$(CONFIG_ARCH_U8500) += ux500/ obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o obj-$(CONFIG_ARCH_ZYNQ) += clk-zynq.o +obj-$(CONFIG_X86) += x86/ # Chip specific obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o diff --git a/drivers/clk/clk-highbank.c b/drivers/clk/clk-highbank.c index 5d1de2e117535820211eac32df13673dea0b81b7..2e08cb00193685eb80e617c386dcb0b31871c122 100644 --- a/drivers/clk/clk-highbank.c +++ b/drivers/clk/clk-highbank.c @@ -182,8 +182,10 @@ static int clk_pll_set_rate(struct clk_hw *hwclk, unsigned long rate, reg |= HB_PLL_EXT_ENA; reg &= ~HB_PLL_EXT_BYPASS; } else { + writel(reg | HB_PLL_EXT_BYPASS, hbclk->reg); reg &= ~HB_PLL_DIVQ_MASK; reg |= divq << HB_PLL_DIVQ_SHIFT; + writel(reg | HB_PLL_EXT_BYPASS, hbclk->reg); } writel(reg, hbclk->reg); diff --git a/drivers/clk/mvebu/clk-gating-ctrl.c b/drivers/clk/mvebu/clk-gating-ctrl.c index 8fa5408b6c7dfeef356ec102d6bf0eab3662835e..ebf141d4374b8abd7c9d955c1b62dfd140d9a57c 100644 --- a/drivers/clk/mvebu/clk-gating-ctrl.c +++ b/drivers/clk/mvebu/clk-gating-ctrl.c @@ -193,6 +193,7 @@ static const struct mvebu_soc_descr __initconst kirkwood_gating_descr[] = { { "runit", NULL, 7 }, { "xor0", NULL, 8 }, { "audio", NULL, 9 }, + { "powersave", "cpuclk", 11 }, { "sata0", NULL, 14 }, { "sata1", NULL, 15 }, { "xor1", NULL, 16 }, diff --git a/drivers/clk/x86/Makefile b/drivers/clk/x86/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..f9ba4fab0ddc8dc8bbae0d1273c86ded4385d93d --- /dev/null +++ b/drivers/clk/x86/Makefile @@ -0,0 +1,2 @@ +clk-x86-lpss-objs := clk-lpss.o clk-lpt.o +obj-$(CONFIG_X86_INTEL_LPSS) += clk-x86-lpss.o diff --git a/drivers/clk/x86/clk-lpss.c b/drivers/clk/x86/clk-lpss.c new file mode 100644 index 0000000000000000000000000000000000000000..b5e229f3c3d9b874d15035d944797464d97c2ad2 --- /dev/null +++ b/drivers/clk/x86/clk-lpss.c @@ -0,0 +1,99 @@ +/* + * Intel Low Power Subsystem clocks. + * + * Copyright (C) 2013, Intel Corporation + * Authors: Mika Westerberg + * Heikki Krogerus + * + * 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. + */ + +#include +#include +#include +#include +#include +#include + +static int clk_lpss_is_mmio_resource(struct acpi_resource *res, void *data) +{ + struct resource r; + return !acpi_dev_resource_memory(res, &r); +} + +static acpi_status clk_lpss_find_mmio(acpi_handle handle, u32 level, + void *data, void **retval) +{ + struct resource_list_entry *rentry; + struct list_head resource_list; + struct acpi_device *adev; + const char *uid = data; + int ret; + + if (acpi_bus_get_device(handle, &adev)) + return AE_OK; + + if (uid) { + if (!adev->pnp.unique_id) + return AE_OK; + if (strcmp(uid, adev->pnp.unique_id)) + return AE_OK; + } + + INIT_LIST_HEAD(&resource_list); + ret = acpi_dev_get_resources(adev, &resource_list, + clk_lpss_is_mmio_resource, NULL); + if (ret < 0) + return AE_NO_MEMORY; + + list_for_each_entry(rentry, &resource_list, node) + if (resource_type(&rentry->res) == IORESOURCE_MEM) { + *(struct resource *)retval = rentry->res; + break; + } + + acpi_dev_free_resource_list(&resource_list); + return AE_OK; +} + +/** + * clk_register_lpss_gate - register LPSS clock gate + * @name: name of this clock gate + * @parent_name: parent clock name + * @hid: ACPI _HID of the device + * @uid: ACPI _UID of the device (optional) + * @offset: LPSS PRV_CLOCK_PARAMS offset + * + * Creates and registers LPSS clock gate. + */ +struct clk *clk_register_lpss_gate(const char *name, const char *parent_name, + const char *hid, const char *uid, + unsigned offset) +{ + struct resource res = { }; + void __iomem *mmio_base; + acpi_status status; + struct clk *clk; + + /* + * First try to look the device and its mmio resource from the + * ACPI namespace. + */ + status = acpi_get_devices(hid, clk_lpss_find_mmio, (void *)uid, + (void **)&res); + if (ACPI_FAILURE(status) || !res.start) + return ERR_PTR(-ENODEV); + + mmio_base = ioremap(res.start, resource_size(&res)); + if (!mmio_base) + return ERR_PTR(-ENOMEM); + + clk = clk_register_gate(NULL, name, parent_name, 0, mmio_base + offset, + 0, 0, NULL); + if (IS_ERR(clk)) + iounmap(mmio_base); + + return clk; +} diff --git a/drivers/clk/x86/clk-lpss.h b/drivers/clk/x86/clk-lpss.h new file mode 100644 index 0000000000000000000000000000000000000000..e9460f442297fcd4448bda227ab2e672ca1a59a0 --- /dev/null +++ b/drivers/clk/x86/clk-lpss.h @@ -0,0 +1,36 @@ +/* + * Intel Low Power Subsystem clock. + * + * Copyright (C) 2013, Intel Corporation + * Authors: Mika Westerberg + * Heikki Krogerus + * + * 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 __CLK_LPSS_H +#define __CLK_LPSS_H + +#include +#include +#include + +#ifdef CONFIG_ACPI +extern struct clk *clk_register_lpss_gate(const char *name, + const char *parent_name, + const char *hid, const char *uid, + unsigned offset); +#else +static inline struct clk *clk_register_lpss_gate(const char *name, + const char *parent_name, + const char *hid, + const char *uid, + unsigned offset) +{ + return ERR_PTR(-ENODEV); +} +#endif + +#endif /* __CLK_LPSS_H */ diff --git a/drivers/clk/x86/clk-lpt.c b/drivers/clk/x86/clk-lpt.c new file mode 100644 index 0000000000000000000000000000000000000000..81298aeef7e3c76999f1d549204f083b1449946c --- /dev/null +++ b/drivers/clk/x86/clk-lpt.c @@ -0,0 +1,86 @@ +/* + * Intel Lynxpoint LPSS clocks. + * + * Copyright (C) 2013, Intel Corporation + * Authors: Mika Westerberg + * Heikki Krogerus + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "clk-lpss.h" + +#define PRV_CLOCK_PARAMS 0x800 + +static int lpt_clk_probe(struct platform_device *pdev) +{ + struct clk *clk; + + /* LPSS free running clock */ + clk = clk_register_fixed_rate(&pdev->dev, "lpss_clk", NULL, CLK_IS_ROOT, + 100000000); + if (IS_ERR(clk)) + return PTR_ERR(clk); + + /* Shared DMA clock */ + clk_register_clkdev(clk, "hclk", "INTL9C60.0.auto"); + + /* SPI clocks */ + clk = clk_register_lpss_gate("spi0_clk", "lpss_clk", "INT33C0", NULL, + PRV_CLOCK_PARAMS); + if (!IS_ERR(clk)) + clk_register_clkdev(clk, NULL, "INT33C0:00"); + + clk = clk_register_lpss_gate("spi1_clk", "lpss_clk", "INT33C1", NULL, + PRV_CLOCK_PARAMS); + if (!IS_ERR(clk)) + clk_register_clkdev(clk, NULL, "INT33C1:00"); + + /* I2C clocks */ + clk = clk_register_lpss_gate("i2c0_clk", "lpss_clk", "INT33C2", NULL, + PRV_CLOCK_PARAMS); + if (!IS_ERR(clk)) + clk_register_clkdev(clk, NULL, "INT33C2:00"); + + clk = clk_register_lpss_gate("i2c1_clk", "lpss_clk", "INT33C3", NULL, + PRV_CLOCK_PARAMS); + if (!IS_ERR(clk)) + clk_register_clkdev(clk, NULL, "INT33C3:00"); + + /* UART clocks */ + clk = clk_register_lpss_gate("uart0_clk", "lpss_clk", "INT33C4", NULL, + PRV_CLOCK_PARAMS); + if (!IS_ERR(clk)) + clk_register_clkdev(clk, NULL, "INT33C4:00"); + + clk = clk_register_lpss_gate("uart1_clk", "lpss_clk", "INT33C5", NULL, + PRV_CLOCK_PARAMS); + if (!IS_ERR(clk)) + clk_register_clkdev(clk, NULL, "INT33C5:00"); + + return 0; +} + +static struct platform_driver lpt_clk_driver = { + .driver = { + .name = "clk-lpt", + .owner = THIS_MODULE, + }, + .probe = lpt_clk_probe, +}; + +static int __init lpt_clk_init(void) +{ + return platform_driver_register(&lpt_clk_driver); +} +arch_initcall(lpt_clk_init); diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index e0a899f25e37445491574f34e8350032d6d228ae..cbcb21e32771df7bf6fb0b18ce9033f5cdc779a5 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -185,7 +185,7 @@ config CPU_FREQ_GOV_CONSERVATIVE If in doubt, say N. config GENERIC_CPUFREQ_CPU0 - bool "Generic CPU0 cpufreq driver" + tristate "Generic CPU0 cpufreq driver" depends on HAVE_CLK && REGULATOR && PM_OPP && OF select CPU_FREQ_TABLE help diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm index a0b3661d90b0e9bcb8a9d4bfe3d3553b61518fff..7f333af1c05990f83205922298c2bd9a4225210d 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm @@ -77,9 +77,39 @@ config ARM_EXYNOS5250_CPUFREQ This adds the CPUFreq driver for Samsung EXYNOS5250 SoC. +config ARM_KIRKWOOD_CPUFREQ + def_bool ARCH_KIRKWOOD && OF + help + This adds the CPUFreq driver for Marvell Kirkwood + SoCs. + +config ARM_IMX6Q_CPUFREQ + tristate "Freescale i.MX6Q cpufreq support" + depends on SOC_IMX6Q + depends on REGULATOR_ANATOP + help + This adds cpufreq driver support for Freescale i.MX6Q SOC. + + If in doubt, say N. + config ARM_SPEAR_CPUFREQ bool "SPEAr CPUFreq support" depends on PLAT_SPEAR default y help This adds the CPUFreq driver support for SPEAr SOCs. + +config ARM_HIGHBANK_CPUFREQ + tristate "Calxeda Highbank-based" + depends on ARCH_HIGHBANK + select CPU_FREQ_TABLE + select GENERIC_CPUFREQ_CPU0 + select PM_OPP + select REGULATOR + + default m + help + This adds the CPUFreq driver for Calxeda Highbank SoC + based boards. + + If in doubt, say N. diff --git a/drivers/cpufreq/Kconfig.x86 b/drivers/cpufreq/Kconfig.x86 index 7227cd7340423c595a2a1b29488e864662198634..98e5abbe8f26e59c933ef8fef9d3f5907381a204 100644 --- a/drivers/cpufreq/Kconfig.x86 +++ b/drivers/cpufreq/Kconfig.x86 @@ -2,6 +2,19 @@ # x86 CPU Frequency scaling drivers # +config X86_INTEL_PSTATE + bool "Intel P state control" + depends on X86 + help + This driver provides a P state for Intel core processors. + The driver implements an internal governor and will become + the scaling driver and governor for Sandy bridge processors. + + When this driver is enabled it will become the perferred + scaling driver for Sandy bridge processors. + + If in doubt, say N. + config X86_PCC_CPUFREQ tristate "Processor Clocking Control interface driver" depends on ACPI && ACPI_PROCESSOR diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index fadc4d496e2fc55383c2f9ddf6c59b9ff2072ec3..5399c45ac31100e2fd08dfa154a40429a2b141cd 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -19,11 +19,12 @@ obj-$(CONFIG_GENERIC_CPUFREQ_CPU0) += cpufreq-cpu0.o ################################################################################## # x86 drivers. # Link order matters. K8 is preferred to ACPI because of firmware bugs in early -# K8 systems. ACPI is preferred to all other hardware-specific drivers. +# K8 systems. This is still the case but acpi-cpufreq errors out so that +# powernow-k8 can load then. ACPI is preferred to all other hardware-specific drivers. # speedstep-* is preferred over p4-clockmod. -obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi-cpufreq.o mperf.o +obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o obj-$(CONFIG_X86_PCC_CPUFREQ) += pcc-cpufreq.o obj-$(CONFIG_X86_POWERNOW_K6) += powernow-k6.o obj-$(CONFIG_X86_POWERNOW_K7) += powernow-k7.o @@ -39,6 +40,7 @@ obj-$(CONFIG_X86_SPEEDSTEP_SMI) += speedstep-smi.o obj-$(CONFIG_X86_SPEEDSTEP_CENTRINO) += speedstep-centrino.o obj-$(CONFIG_X86_P4_CLOCKMOD) += p4-clockmod.o obj-$(CONFIG_X86_CPUFREQ_NFORCE2) += cpufreq-nforce2.o +obj-$(CONFIG_X86_INTEL_PSTATE) += intel_pstate.o ################################################################################## # ARM SoC drivers @@ -50,8 +52,11 @@ obj-$(CONFIG_ARM_EXYNOS_CPUFREQ) += exynos-cpufreq.o obj-$(CONFIG_ARM_EXYNOS4210_CPUFREQ) += exynos4210-cpufreq.o obj-$(CONFIG_ARM_EXYNOS4X12_CPUFREQ) += exynos4x12-cpufreq.o obj-$(CONFIG_ARM_EXYNOS5250_CPUFREQ) += exynos5250-cpufreq.o -obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ) += omap-cpufreq.o +obj-$(CONFIG_ARM_KIRKWOOD_CPUFREQ) += kirkwood-cpufreq.o +obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ) += omap-cpufreq.o obj-$(CONFIG_ARM_SPEAR_CPUFREQ) += spear-cpufreq.o +obj-$(CONFIG_ARM_HIGHBANK_CPUFREQ) += highbank-cpufreq.o +obj-$(CONFIG_ARM_IMX6Q_CPUFREQ) += imx6q-cpufreq.o ################################################################################## # PowerPC platform drivers diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c index 7b0d49d78c61fc6c9fd312b0d05663ad42edf099..937bc286591f9349b5366295fa210412b8ffb756 100644 --- a/drivers/cpufreq/acpi-cpufreq.c +++ b/drivers/cpufreq/acpi-cpufreq.c @@ -734,7 +734,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) #ifdef CONFIG_SMP dmi_check_system(sw_any_bug_dmi_table); - if (bios_with_sw_any_bug && cpumask_weight(policy->cpus) == 1) { + if (bios_with_sw_any_bug && !policy_is_shared(policy)) { policy->shared_type = CPUFREQ_SHARED_TYPE_ALL; cpumask_copy(policy->cpus, cpu_core_mask(cpu)); } @@ -762,6 +762,12 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) switch (perf->control_register.space_id) { case ACPI_ADR_SPACE_SYSTEM_IO: + if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD && + boot_cpu_data.x86 == 0xf) { + pr_debug("AMD K8 systems must use native drivers.\n"); + result = -ENODEV; + goto err_unreg; + } pr_debug("SYSTEM IO addr space\n"); data->cpu_feature = SYSTEM_IO_CAPABLE; break; diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c index debc5a7c8db6207feeb9c428ccc44b8fcaed8d2f..4e5b7fb8927cb5304e3baf37dc3ccb87e71c31b9 100644 --- a/drivers/cpufreq/cpufreq-cpu0.c +++ b/drivers/cpufreq/cpufreq-cpu0.c @@ -12,12 +12,12 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -#include #include #include #include #include #include +#include #include #include @@ -146,7 +146,6 @@ static int cpu0_cpufreq_init(struct cpufreq_policy *policy) * share the clock and voltage and clock. Use cpufreq affected_cpus * interface to have all CPUs scaled together. */ - policy->shared_type = CPUFREQ_SHARED_TYPE_ANY; cpumask_setall(policy->cpus); cpufreq_frequency_table_get_attr(freq_table, policy->cpu); @@ -177,34 +176,32 @@ static struct cpufreq_driver cpu0_cpufreq_driver = { .attr = cpu0_cpufreq_attr, }; -static int cpu0_cpufreq_driver_init(void) +static int cpu0_cpufreq_probe(struct platform_device *pdev) { struct device_node *np; int ret; - np = of_find_node_by_path("/cpus/cpu@0"); + for_each_child_of_node(of_find_node_by_path("/cpus"), np) { + if (of_get_property(np, "operating-points", NULL)) + break; + } + if (!np) { pr_err("failed to find cpu0 node\n"); return -ENOENT; } - cpu_dev = get_cpu_device(0); - if (!cpu_dev) { - pr_err("failed to get cpu0 device\n"); - ret = -ENODEV; - goto out_put_node; - } - + cpu_dev = &pdev->dev; cpu_dev->of_node = np; - cpu_clk = clk_get(cpu_dev, NULL); + cpu_clk = devm_clk_get(cpu_dev, NULL); if (IS_ERR(cpu_clk)) { ret = PTR_ERR(cpu_clk); pr_err("failed to get cpu0 clock: %d\n", ret); goto out_put_node; } - cpu_reg = regulator_get(cpu_dev, "cpu0"); + cpu_reg = devm_regulator_get(cpu_dev, "cpu0"); if (IS_ERR(cpu_reg)) { pr_warn("failed to get cpu0 regulator\n"); cpu_reg = NULL; @@ -267,7 +264,24 @@ static int cpu0_cpufreq_driver_init(void) of_node_put(np); return ret; } -late_initcall(cpu0_cpufreq_driver_init); + +static int cpu0_cpufreq_remove(struct platform_device *pdev) +{ + cpufreq_unregister_driver(&cpu0_cpufreq_driver); + opp_free_cpufreq_table(cpu_dev, &freq_table); + + return 0; +} + +static struct platform_driver cpu0_cpufreq_platdrv = { + .driver = { + .name = "cpufreq-cpu0", + .owner = THIS_MODULE, + }, + .probe = cpu0_cpufreq_probe, + .remove = cpu0_cpufreq_remove, +}; +module_platform_driver(cpu0_cpufreq_platdrv); MODULE_AUTHOR("Shawn Guo "); MODULE_DESCRIPTION("Generic CPU0 cpufreq driver"); diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 1f93dbd723559eb4d92344d0648ea051eef78a84..b02824d092e7ca210d86d70736e2df3f90a61b11 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -59,8 +59,6 @@ static DEFINE_SPINLOCK(cpufreq_driver_lock); * mode before doing so. * * Additional rules: - * - All holders of the lock should check to make sure that the CPU they - * are concerned with are online after they get the lock. * - Governor routines that can be called in cpufreq hotplug path should not * take this sem as top level hotplug notifier handler takes this. * - Lock should not be held across @@ -70,38 +68,28 @@ static DEFINE_PER_CPU(int, cpufreq_policy_cpu); 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 int lock_policy_rwsem_##mode(int cpu) \ { \ int policy_cpu = per_cpu(cpufreq_policy_cpu, cpu); \ BUG_ON(policy_cpu == -1); \ down_##mode(&per_cpu(cpu_policy_rwsem, policy_cpu)); \ - if (unlikely(!cpu_online(cpu))) { \ - up_##mode(&per_cpu(cpu_policy_rwsem, policy_cpu)); \ - return -1; \ - } \ \ return 0; \ } lock_policy_rwsem(read, cpu); - lock_policy_rwsem(write, cpu); -static void unlock_policy_rwsem_read(int cpu) -{ - int policy_cpu = per_cpu(cpufreq_policy_cpu, cpu); - BUG_ON(policy_cpu == -1); - up_read(&per_cpu(cpu_policy_rwsem, policy_cpu)); -} - -static void unlock_policy_rwsem_write(int cpu) -{ - int policy_cpu = per_cpu(cpufreq_policy_cpu, cpu); - BUG_ON(policy_cpu == -1); - up_write(&per_cpu(cpu_policy_rwsem, policy_cpu)); +#define unlock_policy_rwsem(mode, cpu) \ +static void unlock_policy_rwsem_##mode(int cpu) \ +{ \ + int policy_cpu = per_cpu(cpufreq_policy_cpu, cpu); \ + BUG_ON(policy_cpu == -1); \ + up_##mode(&per_cpu(cpu_policy_rwsem, policy_cpu)); \ } +unlock_policy_rwsem(read, cpu); +unlock_policy_rwsem(write, cpu); /* internal prototypes */ static int __cpufreq_governor(struct cpufreq_policy *policy, @@ -180,6 +168,9 @@ static struct cpufreq_policy *__cpufreq_cpu_get(unsigned int cpu, bool sysfs) struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu) { + if (cpufreq_disabled()) + return NULL; + return __cpufreq_cpu_get(cpu, false); } EXPORT_SYMBOL_GPL(cpufreq_cpu_get); @@ -198,6 +189,9 @@ static void __cpufreq_cpu_put(struct cpufreq_policy *data, bool sysfs) void cpufreq_cpu_put(struct cpufreq_policy *data) { + if (cpufreq_disabled()) + return; + __cpufreq_cpu_put(data, false); } EXPORT_SYMBOL_GPL(cpufreq_cpu_put); @@ -261,14 +255,21 @@ static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state) { struct cpufreq_policy *policy; + unsigned long flags; BUG_ON(irqs_disabled()); + if (cpufreq_disabled()) + return; + freqs->flags = cpufreq_driver->flags; pr_debug("notification %u of frequency transition to %u kHz\n", state, freqs->new); + spin_lock_irqsave(&cpufreq_driver_lock, flags); policy = per_cpu(cpufreq_cpu_data, freqs->cpu); + spin_unlock_irqrestore(&cpufreq_driver_lock, flags); + switch (state) { case CPUFREQ_PRECHANGE: @@ -294,7 +295,6 @@ void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state) adjust_jiffies(CPUFREQ_POSTCHANGE, freqs); pr_debug("FREQ: %lu - CPU: %lu", (unsigned long)freqs->new, (unsigned long)freqs->cpu); - trace_power_frequency(POWER_PSTATE, freqs->new, freqs->cpu); trace_cpu_frequency(freqs->new, freqs->cpu); srcu_notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_POSTCHANGE, freqs); @@ -543,8 +543,6 @@ static ssize_t show_cpus(const struct cpumask *mask, char *buf) */ static ssize_t show_related_cpus(struct cpufreq_policy *policy, char *buf) { - if (cpumask_empty(policy->related_cpus)) - return show_cpus(policy->cpus, buf); return show_cpus(policy->related_cpus, buf); } @@ -700,87 +698,6 @@ static struct kobj_type ktype_cpufreq = { .release = cpufreq_sysfs_release, }; -/* - * Returns: - * Negative: Failure - * 0: Success - * Positive: When we have a managed CPU and the sysfs got symlinked - */ -static int cpufreq_add_dev_policy(unsigned int cpu, - struct cpufreq_policy *policy, - struct device *dev) -{ - int ret = 0; -#ifdef CONFIG_SMP - unsigned long flags; - unsigned int j; -#ifdef CONFIG_HOTPLUG_CPU - struct cpufreq_governor *gov; - - gov = __find_governor(per_cpu(cpufreq_cpu_governor, cpu)); - if (gov) { - policy->governor = gov; - pr_debug("Restoring governor %s for cpu %d\n", - policy->governor->name, cpu); - } -#endif - - for_each_cpu(j, policy->cpus) { - struct cpufreq_policy *managed_policy; - - if (cpu == j) - continue; - - /* Check for existing affected CPUs. - * They may not be aware of it due to CPU Hotplug. - * cpufreq_cpu_put is called when the device is removed - * in __cpufreq_remove_dev() - */ - managed_policy = cpufreq_cpu_get(j); - if (unlikely(managed_policy)) { - - /* Set proper policy_cpu */ - unlock_policy_rwsem_write(cpu); - per_cpu(cpufreq_policy_cpu, cpu) = managed_policy->cpu; - - if (lock_policy_rwsem_write(cpu) < 0) { - /* Should not go through policy unlock path */ - if (cpufreq_driver->exit) - cpufreq_driver->exit(policy); - cpufreq_cpu_put(managed_policy); - return -EBUSY; - } - - spin_lock_irqsave(&cpufreq_driver_lock, flags); - cpumask_copy(managed_policy->cpus, policy->cpus); - per_cpu(cpufreq_cpu_data, cpu) = managed_policy; - spin_unlock_irqrestore(&cpufreq_driver_lock, flags); - - pr_debug("CPU already managed, adding link\n"); - ret = sysfs_create_link(&dev->kobj, - &managed_policy->kobj, - "cpufreq"); - if (ret) - cpufreq_cpu_put(managed_policy); - /* - * Success. We only needed to be added to the mask. - * Call driver->exit() because only the cpu parent of - * the kobj needed to call init(). - */ - if (cpufreq_driver->exit) - cpufreq_driver->exit(policy); - - if (!ret) - return 1; - else - return ret; - } - } -#endif - return ret; -} - - /* symlink affected CPUs */ static int cpufreq_add_dev_symlink(unsigned int cpu, struct cpufreq_policy *policy) @@ -794,8 +711,6 @@ static int cpufreq_add_dev_symlink(unsigned int cpu, if (j == cpu) continue; - if (!cpu_online(j)) - continue; pr_debug("CPU %u already managed, adding link\n", j); managed_policy = cpufreq_cpu_get(cpu); @@ -852,8 +767,6 @@ static int cpufreq_add_dev_interface(unsigned int cpu, spin_lock_irqsave(&cpufreq_driver_lock, flags); for_each_cpu(j, policy->cpus) { - if (!cpu_online(j)) - continue; per_cpu(cpufreq_cpu_data, j) = policy; per_cpu(cpufreq_policy_cpu, j) = policy->cpu; } @@ -885,6 +798,42 @@ static int cpufreq_add_dev_interface(unsigned int cpu, return ret; } +#ifdef CONFIG_HOTPLUG_CPU +static int cpufreq_add_policy_cpu(unsigned int cpu, unsigned int sibling, + struct device *dev) +{ + struct cpufreq_policy *policy; + int ret = 0; + unsigned long flags; + + policy = cpufreq_cpu_get(sibling); + WARN_ON(!policy); + + __cpufreq_governor(policy, CPUFREQ_GOV_STOP); + + lock_policy_rwsem_write(sibling); + + spin_lock_irqsave(&cpufreq_driver_lock, flags); + + cpumask_set_cpu(cpu, policy->cpus); + per_cpu(cpufreq_policy_cpu, cpu) = policy->cpu; + per_cpu(cpufreq_cpu_data, cpu) = policy; + spin_unlock_irqrestore(&cpufreq_driver_lock, flags); + + unlock_policy_rwsem_write(sibling); + + __cpufreq_governor(policy, CPUFREQ_GOV_START); + __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS); + + ret = sysfs_create_link(&dev->kobj, &policy->kobj, "cpufreq"); + if (ret) { + cpufreq_cpu_put(policy); + return ret; + } + + return 0; +} +#endif /** * cpufreq_add_dev - add a CPU device @@ -897,12 +846,12 @@ static int cpufreq_add_dev_interface(unsigned int cpu, */ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) { - unsigned int cpu = dev->id; - int ret = 0, found = 0; + unsigned int j, cpu = dev->id; + int ret = -ENOMEM; struct cpufreq_policy *policy; unsigned long flags; - unsigned int j; #ifdef CONFIG_HOTPLUG_CPU + struct cpufreq_governor *gov; int sibling; #endif @@ -919,6 +868,19 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) cpufreq_cpu_put(policy); return 0; } + +#ifdef CONFIG_HOTPLUG_CPU + /* Check if this cpu was hot-unplugged earlier and has siblings */ + spin_lock_irqsave(&cpufreq_driver_lock, flags); + for_each_online_cpu(sibling) { + struct cpufreq_policy *cp = per_cpu(cpufreq_cpu_data, sibling); + if (cp && cpumask_test_cpu(cpu, cp->related_cpus)) { + spin_unlock_irqrestore(&cpufreq_driver_lock, flags); + return cpufreq_add_policy_cpu(cpu, sibling, dev); + } + } + spin_unlock_irqrestore(&cpufreq_driver_lock, flags); +#endif #endif if (!try_module_get(cpufreq_driver->owner)) { @@ -926,7 +888,6 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) goto module_out; } - ret = -ENOMEM; policy = kzalloc(sizeof(struct cpufreq_policy), GFP_KERNEL); if (!policy) goto nomem_out; @@ -938,66 +899,58 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) goto err_free_cpumask; policy->cpu = cpu; + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; cpumask_copy(policy->cpus, cpumask_of(cpu)); /* Initially set CPU itself as the policy_cpu */ per_cpu(cpufreq_policy_cpu, cpu) = cpu; - ret = (lock_policy_rwsem_write(cpu) < 0); - WARN_ON(ret); init_completion(&policy->kobj_unregister); INIT_WORK(&policy->update, handle_update); - /* Set governor before ->init, so that driver could check it */ -#ifdef CONFIG_HOTPLUG_CPU - for_each_online_cpu(sibling) { - struct cpufreq_policy *cp = per_cpu(cpufreq_cpu_data, sibling); - if (cp && cp->governor && - (cpumask_test_cpu(cpu, cp->related_cpus))) { - policy->governor = cp->governor; - found = 1; - break; - } - } -#endif - if (!found) - policy->governor = CPUFREQ_DEFAULT_GOVERNOR; /* call driver. From then on the cpufreq must be able * to accept all calls to ->verify and ->setpolicy for this CPU */ ret = cpufreq_driver->init(policy); if (ret) { pr_debug("initialization failed\n"); - goto err_unlock_policy; + goto err_set_policy_cpu; } + + /* related cpus should atleast have policy->cpus */ + cpumask_or(policy->related_cpus, policy->related_cpus, policy->cpus); + + /* + * affected cpus must always be the one, which are online. We aren't + * managing offline cpus here. + */ + cpumask_and(policy->cpus, policy->cpus, cpu_online_mask); + policy->user_policy.min = policy->min; policy->user_policy.max = policy->max; blocking_notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_START, policy); - ret = cpufreq_add_dev_policy(cpu, policy, dev); - if (ret) { - if (ret > 0) - /* This is a managed cpu, symlink created, - exit with 0 */ - ret = 0; - goto err_unlock_policy; +#ifdef CONFIG_HOTPLUG_CPU + gov = __find_governor(per_cpu(cpufreq_cpu_governor, cpu)); + if (gov) { + policy->governor = gov; + pr_debug("Restoring governor %s for cpu %d\n", + policy->governor->name, cpu); } +#endif ret = cpufreq_add_dev_interface(cpu, policy, dev); if (ret) goto err_out_unregister; - unlock_policy_rwsem_write(cpu); - kobject_uevent(&policy->kobj, KOBJ_ADD); module_put(cpufreq_driver->owner); pr_debug("initialization complete\n"); return 0; - err_out_unregister: spin_lock_irqsave(&cpufreq_driver_lock, flags); for_each_cpu(j, policy->cpus) @@ -1007,8 +960,8 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) kobject_put(&policy->kobj); wait_for_completion(&policy->kobj_unregister); -err_unlock_policy: - unlock_policy_rwsem_write(cpu); +err_set_policy_cpu: + per_cpu(cpufreq_policy_cpu, cpu) = -1; free_cpumask_var(policy->related_cpus); err_free_cpumask: free_cpumask_var(policy->cpus); @@ -1020,6 +973,22 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) return ret; } +static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu) +{ + int j; + + policy->last_cpu = policy->cpu; + policy->cpu = cpu; + + for_each_cpu(j, policy->cpus) + per_cpu(cpufreq_policy_cpu, j) = 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); +} /** * __cpufreq_remove_dev - remove a CPU device @@ -1030,129 +999,103 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) */ static int __cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif) { - unsigned int cpu = dev->id; + unsigned int cpu = dev->id, ret, cpus; unsigned long flags; struct cpufreq_policy *data; struct kobject *kobj; struct completion *cmp; -#ifdef CONFIG_SMP struct device *cpu_dev; - unsigned int j; -#endif - pr_debug("unregistering CPU %u\n", cpu); + pr_debug("%s: unregistering CPU %u\n", __func__, cpu); spin_lock_irqsave(&cpufreq_driver_lock, flags); + data = per_cpu(cpufreq_cpu_data, cpu); + per_cpu(cpufreq_cpu_data, cpu) = NULL; + + spin_unlock_irqrestore(&cpufreq_driver_lock, flags); if (!data) { - spin_unlock_irqrestore(&cpufreq_driver_lock, flags); - unlock_policy_rwsem_write(cpu); + pr_debug("%s: No cpu_data found\n", __func__); return -EINVAL; } - per_cpu(cpufreq_cpu_data, cpu) = NULL; + if (cpufreq_driver->target) + __cpufreq_governor(data, CPUFREQ_GOV_STOP); -#ifdef CONFIG_SMP - /* if this isn't the CPU which is the parent of the kobj, we - * only need to unlink, put and exit - */ - if (unlikely(cpu != data->cpu)) { - pr_debug("removing link\n"); - cpumask_clear_cpu(cpu, data->cpus); - spin_unlock_irqrestore(&cpufreq_driver_lock, flags); - kobj = &dev->kobj; - cpufreq_cpu_put(data); - unlock_policy_rwsem_write(cpu); - sysfs_remove_link(kobj, "cpufreq"); - return 0; - } +#ifdef CONFIG_HOTPLUG_CPU + if (!cpufreq_driver->setpolicy) + strncpy(per_cpu(cpufreq_cpu_governor, cpu), + data->governor->name, CPUFREQ_NAME_LEN); #endif -#ifdef CONFIG_SMP + WARN_ON(lock_policy_rwsem_write(cpu)); + cpus = cpumask_weight(data->cpus); + cpumask_clear_cpu(cpu, data->cpus); + unlock_policy_rwsem_write(cpu); -#ifdef CONFIG_HOTPLUG_CPU - strncpy(per_cpu(cpufreq_cpu_governor, cpu), data->governor->name, - CPUFREQ_NAME_LEN); -#endif + if (cpu != data->cpu) { + sysfs_remove_link(&dev->kobj, "cpufreq"); + } else if (cpus > 1) { + /* first sibling now owns the new sysfs dir */ + cpu_dev = get_cpu_device(cpumask_first(data->cpus)); + sysfs_remove_link(&cpu_dev->kobj, "cpufreq"); + ret = kobject_move(&data->kobj, &cpu_dev->kobj); + if (ret) { + pr_err("%s: Failed to move kobj: %d", __func__, ret); - /* if we have other CPUs still registered, we need to unlink them, - * or else wait_for_completion below will lock up. Clean the - * per_cpu(cpufreq_cpu_data) while holding the lock, and remove - * the sysfs links afterwards. - */ - if (unlikely(cpumask_weight(data->cpus) > 1)) { - for_each_cpu(j, data->cpus) { - if (j == cpu) - continue; - per_cpu(cpufreq_cpu_data, j) = NULL; - } - } + WARN_ON(lock_policy_rwsem_write(cpu)); + cpumask_set_cpu(cpu, data->cpus); - spin_unlock_irqrestore(&cpufreq_driver_lock, flags); + spin_lock_irqsave(&cpufreq_driver_lock, flags); + per_cpu(cpufreq_cpu_data, cpu) = data; + spin_unlock_irqrestore(&cpufreq_driver_lock, flags); - if (unlikely(cpumask_weight(data->cpus) > 1)) { - for_each_cpu(j, data->cpus) { - if (j == cpu) - continue; - pr_debug("removing link for cpu %u\n", j); -#ifdef CONFIG_HOTPLUG_CPU - strncpy(per_cpu(cpufreq_cpu_governor, j), - data->governor->name, CPUFREQ_NAME_LEN); -#endif - cpu_dev = get_cpu_device(j); - kobj = &cpu_dev->kobj; unlock_policy_rwsem_write(cpu); - sysfs_remove_link(kobj, "cpufreq"); - lock_policy_rwsem_write(cpu); - cpufreq_cpu_put(data); - } - } -#else - spin_unlock_irqrestore(&cpufreq_driver_lock, flags); -#endif - if (cpufreq_driver->target) - __cpufreq_governor(data, CPUFREQ_GOV_STOP); + ret = sysfs_create_link(&cpu_dev->kobj, &data->kobj, + "cpufreq"); + return -EINVAL; + } - kobj = &data->kobj; - cmp = &data->kobj_unregister; - unlock_policy_rwsem_write(cpu); - kobject_put(kobj); + WARN_ON(lock_policy_rwsem_write(cpu)); + update_policy_cpu(data, cpu_dev->id); + unlock_policy_rwsem_write(cpu); + pr_debug("%s: policy Kobject moved to cpu: %d from: %d\n", + __func__, cpu_dev->id, cpu); + } - /* we need to make sure that the underlying kobj is actually - * not referenced anymore by anybody before we proceed with - * unloading. - */ - pr_debug("waiting for dropping of refcount\n"); - wait_for_completion(cmp); - pr_debug("wait complete\n"); + pr_debug("%s: removing link, cpu: %d\n", __func__, cpu); + cpufreq_cpu_put(data); - lock_policy_rwsem_write(cpu); - if (cpufreq_driver->exit) - cpufreq_driver->exit(data); - unlock_policy_rwsem_write(cpu); + /* If cpu is last user of policy, free policy */ + if (cpus == 1) { + lock_policy_rwsem_read(cpu); + kobj = &data->kobj; + cmp = &data->kobj_unregister; + unlock_policy_rwsem_read(cpu); + kobject_put(kobj); + + /* we need to make sure that the underlying kobj is actually + * not referenced anymore by anybody before we proceed with + * unloading. + */ + pr_debug("waiting for dropping of refcount\n"); + wait_for_completion(cmp); + pr_debug("wait complete\n"); -#ifdef CONFIG_HOTPLUG_CPU - /* when the CPU which is the parent of the kobj is hotplugged - * offline, check for siblings, and create cpufreq sysfs interface - * and symlinks - */ - if (unlikely(cpumask_weight(data->cpus) > 1)) { - /* first sibling now owns the new sysfs dir */ - cpumask_clear_cpu(cpu, data->cpus); - cpufreq_add_dev(get_cpu_device(cpumask_first(data->cpus)), NULL); + if (cpufreq_driver->exit) + cpufreq_driver->exit(data); - /* finally remove our own symlink */ - lock_policy_rwsem_write(cpu); - __cpufreq_remove_dev(dev, sif); + free_cpumask_var(data->related_cpus); + free_cpumask_var(data->cpus); + kfree(data); + } else if (cpufreq_driver->target) { + __cpufreq_governor(data, CPUFREQ_GOV_START); + __cpufreq_governor(data, CPUFREQ_GOV_LIMITS); } -#endif - - free_cpumask_var(data->related_cpus); - free_cpumask_var(data->cpus); - kfree(data); + per_cpu(cpufreq_policy_cpu, cpu) = -1; return 0; } @@ -1165,9 +1108,6 @@ static int cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif) if (cpu_is_offline(cpu)) return 0; - if (unlikely(lock_policy_rwsem_write(cpu))) - BUG(); - retval = __cpufreq_remove_dev(dev, sif); return retval; } @@ -1216,9 +1156,13 @@ static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq, */ unsigned int cpufreq_quick_get(unsigned int cpu) { - struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); + struct cpufreq_policy *policy; unsigned int ret_freq = 0; + if (cpufreq_driver && cpufreq_driver->setpolicy && cpufreq_driver->get) + return cpufreq_driver->get(cpu); + + policy = cpufreq_cpu_get(cpu); if (policy) { ret_freq = policy->cur; cpufreq_cpu_put(policy); @@ -1386,6 +1330,20 @@ static struct syscore_ops cpufreq_syscore_ops = { .resume = cpufreq_bp_resume, }; +/** + * cpufreq_get_current_driver - return current driver's name + * + * Return the name string of the currently loaded cpufreq driver + * or NULL, if none. + */ +const char *cpufreq_get_current_driver(void) +{ + if (cpufreq_driver) + return cpufreq_driver->name; + + return NULL; +} +EXPORT_SYMBOL_GPL(cpufreq_get_current_driver); /********************************************************************* * NOTIFIER LISTS INTERFACE * @@ -1408,6 +1366,9 @@ int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list) { int ret; + if (cpufreq_disabled()) + return -EINVAL; + WARN_ON(!init_cpufreq_transition_notifier_list_called); switch (list) { @@ -1442,6 +1403,9 @@ int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list) { int ret; + if (cpufreq_disabled()) + return -EINVAL; + switch (list) { case CPUFREQ_TRANSITION_NOTIFIER: ret = srcu_notifier_chain_unregister( @@ -1487,7 +1451,7 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy, if (target_freq == policy->cur) return 0; - if (cpu_online(policy->cpu) && cpufreq_driver->target) + if (cpufreq_driver->target) retval = cpufreq_driver->target(policy, target_freq, relation); return retval; @@ -1522,7 +1486,10 @@ int __cpufreq_driver_getavg(struct cpufreq_policy *policy, unsigned int cpu) { int ret = 0; - if (!(cpu_online(cpu) && cpufreq_driver->getavg)) + if (cpufreq_disabled()) + return ret; + + if (!cpufreq_driver->getavg) return 0; policy = cpufreq_cpu_get(policy->cpu); @@ -1577,6 +1544,11 @@ static int __cpufreq_governor(struct cpufreq_policy *policy, policy->cpu, event); ret = policy->governor->governor(policy, event); + if (event == CPUFREQ_GOV_START) + policy->governor->initialized++; + else if (event == CPUFREQ_GOV_STOP) + policy->governor->initialized--; + /* we keep one module reference alive for each CPU governed by this CPU */ if ((event != CPUFREQ_GOV_START) || ret) @@ -1600,6 +1572,7 @@ int cpufreq_register_governor(struct cpufreq_governor *governor) mutex_lock(&cpufreq_governor_mutex); + governor->initialized = 0; err = -EBUSY; if (__find_governor(governor->name) == NULL) { err = 0; @@ -1797,7 +1770,7 @@ int cpufreq_update_policy(unsigned int cpu) pr_debug("Driver did not initialize current freq"); data->cur = policy.cur; } else { - if (data->cur != policy.cur) + if (data->cur != policy.cur && cpufreq_driver->target) cpufreq_out_of_sync(cpu, data->cur, policy.cur); } @@ -1829,9 +1802,6 @@ static int __cpuinit cpufreq_cpu_callback(struct notifier_block *nfb, break; case CPU_DOWN_PREPARE: case CPU_DOWN_PREPARE_FROZEN: - if (unlikely(lock_policy_rwsem_write(cpu))) - BUG(); - __cpufreq_remove_dev(dev, NULL); break; case CPU_DOWN_FAILED: diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index 64ef737e7e72979aa5d29a865d8ff4b9db4206cb..4fd0006b129104d430c6d433bdde161a301383dd 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c @@ -25,7 +25,7 @@ #include "cpufreq_governor.h" -/* Conservative governor macors */ +/* Conservative governor macros */ #define DEF_FREQUENCY_UP_THRESHOLD (80) #define DEF_FREQUENCY_DOWN_THRESHOLD (20) #define DEF_SAMPLING_DOWN_FACTOR (1) @@ -113,17 +113,20 @@ static void cs_check_cpu(int cpu, unsigned int load) static void cs_dbs_timer(struct work_struct *work) { + struct delayed_work *dw = to_delayed_work(work); struct cs_cpu_dbs_info_s *dbs_info = container_of(work, struct cs_cpu_dbs_info_s, cdbs.work.work); - unsigned int cpu = dbs_info->cdbs.cpu; + unsigned int cpu = dbs_info->cdbs.cur_policy->cpu; + struct cs_cpu_dbs_info_s *core_dbs_info = &per_cpu(cs_cpu_dbs_info, + cpu); int delay = delay_for_sampling_rate(cs_tuners.sampling_rate); - mutex_lock(&dbs_info->cdbs.timer_mutex); + mutex_lock(&core_dbs_info->cdbs.timer_mutex); + if (need_load_eval(&core_dbs_info->cdbs, cs_tuners.sampling_rate)) + dbs_check_cpu(&cs_dbs_data, cpu); - dbs_check_cpu(&cs_dbs_data, cpu); - - schedule_delayed_work_on(cpu, &dbs_info->cdbs.work, delay); - mutex_unlock(&dbs_info->cdbs.timer_mutex); + schedule_delayed_work_on(smp_processor_id(), dw, delay); + mutex_unlock(&core_dbs_info->cdbs.timer_mutex); } static int dbs_cpufreq_notifier(struct notifier_block *nb, unsigned long val, @@ -141,7 +144,7 @@ static int dbs_cpufreq_notifier(struct notifier_block *nb, unsigned long val, /* * we only care if our internally tracked freq moves outside the 'valid' - * ranges of freqency available to us otherwise we do not change it + * ranges of frequency available to us otherwise we do not change it */ if (dbs_info->requested_freq > policy->max || dbs_info->requested_freq < policy->min) diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c index 6c5f1d383cdce86b783fc37077798a8a980c4116..5a76086ff09becd77fff867d05b6f2782da50f0f 100644 --- a/drivers/cpufreq/cpufreq_governor.c +++ b/drivers/cpufreq/cpufreq_governor.c @@ -161,25 +161,48 @@ void dbs_check_cpu(struct dbs_data *dbs_data, int cpu) } EXPORT_SYMBOL_GPL(dbs_check_cpu); -static inline void dbs_timer_init(struct dbs_data *dbs_data, - struct cpu_dbs_common_info *cdbs, unsigned int sampling_rate) +static inline void dbs_timer_init(struct dbs_data *dbs_data, int cpu, + unsigned int sampling_rate) { int delay = delay_for_sampling_rate(sampling_rate); + struct cpu_dbs_common_info *cdbs = dbs_data->get_cpu_cdbs(cpu); - INIT_DEFERRABLE_WORK(&cdbs->work, dbs_data->gov_dbs_timer); - schedule_delayed_work_on(cdbs->cpu, &cdbs->work, delay); + schedule_delayed_work_on(cpu, &cdbs->work, delay); } -static inline void dbs_timer_exit(struct cpu_dbs_common_info *cdbs) +static inline void dbs_timer_exit(struct dbs_data *dbs_data, int cpu) { + struct cpu_dbs_common_info *cdbs = dbs_data->get_cpu_cdbs(cpu); + cancel_delayed_work_sync(&cdbs->work); } +/* Will return if we need to evaluate cpu load again or not */ +bool need_load_eval(struct cpu_dbs_common_info *cdbs, + unsigned int sampling_rate) +{ + if (policy_is_shared(cdbs->cur_policy)) { + ktime_t time_now = ktime_get(); + s64 delta_us = ktime_us_delta(time_now, cdbs->time_stamp); + + /* Do nothing if we recently have sampled */ + if (delta_us < (s64)(sampling_rate / 2)) + return false; + else + cdbs->time_stamp = time_now; + } + + return true; +} +EXPORT_SYMBOL_GPL(need_load_eval); + int cpufreq_governor_dbs(struct dbs_data *dbs_data, struct cpufreq_policy *policy, unsigned int event) { struct od_cpu_dbs_info_s *od_dbs_info = NULL; struct cs_cpu_dbs_info_s *cs_dbs_info = NULL; + struct cs_ops *cs_ops = NULL; + struct od_ops *od_ops = NULL; struct od_dbs_tuners *od_tuners = dbs_data->tuners; struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; struct cpu_dbs_common_info *cpu_cdbs; @@ -192,109 +215,111 @@ int cpufreq_governor_dbs(struct dbs_data *dbs_data, cs_dbs_info = dbs_data->get_cpu_dbs_info_s(cpu); sampling_rate = &cs_tuners->sampling_rate; ignore_nice = cs_tuners->ignore_nice; + cs_ops = dbs_data->gov_ops; } else { od_dbs_info = dbs_data->get_cpu_dbs_info_s(cpu); sampling_rate = &od_tuners->sampling_rate; ignore_nice = od_tuners->ignore_nice; + od_ops = dbs_data->gov_ops; } switch (event) { case CPUFREQ_GOV_START: - if ((!cpu_online(cpu)) || (!policy->cur)) + if (!policy->cur) return -EINVAL; mutex_lock(&dbs_data->mutex); - dbs_data->enable++; - cpu_cdbs->cpu = cpu; for_each_cpu(j, policy->cpus) { - struct cpu_dbs_common_info *j_cdbs; - j_cdbs = dbs_data->get_cpu_cdbs(j); + struct cpu_dbs_common_info *j_cdbs = + dbs_data->get_cpu_cdbs(j); + j_cdbs->cpu = j; j_cdbs->cur_policy = policy; j_cdbs->prev_cpu_idle = get_cpu_idle_time(j, &j_cdbs->prev_cpu_wall); if (ignore_nice) j_cdbs->prev_cpu_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE]; - } - /* - * Start the timerschedule work, when this governor is used for - * first time - */ - if (dbs_data->enable != 1) - goto second_time; - - rc = sysfs_create_group(cpufreq_global_kobject, - dbs_data->attr_group); - if (rc) { - mutex_unlock(&dbs_data->mutex); - return rc; + mutex_init(&j_cdbs->timer_mutex); + INIT_DEFERRABLE_WORK(&j_cdbs->work, + dbs_data->gov_dbs_timer); } - /* policy latency is in nS. Convert it to uS first */ - latency = policy->cpuinfo.transition_latency / 1000; - if (latency == 0) - latency = 1; + if (!policy->governor->initialized) { + rc = sysfs_create_group(cpufreq_global_kobject, + dbs_data->attr_group); + if (rc) { + mutex_unlock(&dbs_data->mutex); + return rc; + } + } /* * conservative does not implement micro like ondemand * governor, thus we are bound to jiffes/HZ */ if (dbs_data->governor == GOV_CONSERVATIVE) { - struct cs_ops *ops = dbs_data->gov_ops; + cs_dbs_info->down_skip = 0; + cs_dbs_info->enable = 1; + cs_dbs_info->requested_freq = policy->cur; - cpufreq_register_notifier(ops->notifier_block, - CPUFREQ_TRANSITION_NOTIFIER); + if (!policy->governor->initialized) { + cpufreq_register_notifier(cs_ops->notifier_block, + CPUFREQ_TRANSITION_NOTIFIER); - dbs_data->min_sampling_rate = MIN_SAMPLING_RATE_RATIO * - jiffies_to_usecs(10); + dbs_data->min_sampling_rate = + MIN_SAMPLING_RATE_RATIO * + jiffies_to_usecs(10); + } } else { - struct od_ops *ops = dbs_data->gov_ops; + od_dbs_info->rate_mult = 1; + od_dbs_info->sample_type = OD_NORMAL_SAMPLE; + od_ops->powersave_bias_init_cpu(cpu); - od_tuners->io_is_busy = ops->io_busy(); + if (!policy->governor->initialized) + od_tuners->io_is_busy = od_ops->io_busy(); } + if (policy->governor->initialized) + goto unlock; + + /* policy latency is in nS. Convert it to uS first */ + latency = policy->cpuinfo.transition_latency / 1000; + if (latency == 0) + latency = 1; + /* Bring kernel and HW constraints together */ dbs_data->min_sampling_rate = max(dbs_data->min_sampling_rate, MIN_LATENCY_MULTIPLIER * latency); *sampling_rate = max(dbs_data->min_sampling_rate, latency * LATENCY_MULTIPLIER); - -second_time: - if (dbs_data->governor == GOV_CONSERVATIVE) { - cs_dbs_info->down_skip = 0; - cs_dbs_info->enable = 1; - cs_dbs_info->requested_freq = policy->cur; - } else { - struct od_ops *ops = dbs_data->gov_ops; - od_dbs_info->rate_mult = 1; - od_dbs_info->sample_type = OD_NORMAL_SAMPLE; - ops->powersave_bias_init_cpu(cpu); - } +unlock: mutex_unlock(&dbs_data->mutex); - mutex_init(&cpu_cdbs->timer_mutex); - dbs_timer_init(dbs_data, cpu_cdbs, *sampling_rate); + /* Initiate timer time stamp */ + cpu_cdbs->time_stamp = ktime_get(); + + for_each_cpu(j, policy->cpus) + dbs_timer_init(dbs_data, j, *sampling_rate); break; case CPUFREQ_GOV_STOP: if (dbs_data->governor == GOV_CONSERVATIVE) cs_dbs_info->enable = 0; - dbs_timer_exit(cpu_cdbs); + for_each_cpu(j, policy->cpus) + dbs_timer_exit(dbs_data, j); mutex_lock(&dbs_data->mutex); mutex_destroy(&cpu_cdbs->timer_mutex); - dbs_data->enable--; - if (!dbs_data->enable) { - struct cs_ops *ops = dbs_data->gov_ops; + if (policy->governor->initialized == 1) { sysfs_remove_group(cpufreq_global_kobject, dbs_data->attr_group); if (dbs_data->governor == GOV_CONSERVATIVE) - cpufreq_unregister_notifier(ops->notifier_block, + cpufreq_unregister_notifier(cs_ops->notifier_block, CPUFREQ_TRANSITION_NOTIFIER); } mutex_unlock(&dbs_data->mutex); diff --git a/drivers/cpufreq/cpufreq_governor.h b/drivers/cpufreq/cpufreq_governor.h index f6616540c53d929043ca1fb2b7ed4ce64a6739b0..d2ac911506006be9e1c77b1e57853828c33fd99a 100644 --- a/drivers/cpufreq/cpufreq_governor.h +++ b/drivers/cpufreq/cpufreq_governor.h @@ -82,6 +82,7 @@ struct cpu_dbs_common_info { * the governor or limits. */ struct mutex timer_mutex; + ktime_t time_stamp; }; struct od_cpu_dbs_info_s { @@ -108,7 +109,7 @@ struct od_dbs_tuners { unsigned int sampling_rate; unsigned int sampling_down_factor; unsigned int up_threshold; - unsigned int down_differential; + unsigned int adj_up_threshold; unsigned int powersave_bias; unsigned int io_is_busy; }; @@ -129,7 +130,6 @@ struct dbs_data { #define GOV_CONSERVATIVE 1 int governor; unsigned int min_sampling_rate; - unsigned int enable; /* number of CPUs using this policy */ struct attribute_group *attr_group; void *tuners; @@ -171,6 +171,8 @@ static inline int delay_for_sampling_rate(unsigned int sampling_rate) u64 get_cpu_idle_time(unsigned int cpu, u64 *wall); void dbs_check_cpu(struct dbs_data *dbs_data, int cpu); +bool need_load_eval(struct cpu_dbs_common_info *cdbs, + unsigned int sampling_rate); int cpufreq_governor_dbs(struct dbs_data *dbs_data, struct cpufreq_policy *policy, unsigned int event); #endif /* _CPUFREQ_GOVERNER_H */ diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 7731f7c7e79ae162a51a5d57c6a4366492d2c810..f3eb26cd848fa7afe495d09db9f6ad166c3501b6 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -26,7 +26,7 @@ #include "cpufreq_governor.h" -/* On-demand governor macors */ +/* On-demand governor macros */ #define DEF_FREQUENCY_DOWN_DIFFERENTIAL (10) #define DEF_FREQUENCY_UP_THRESHOLD (80) #define DEF_SAMPLING_DOWN_FACTOR (1) @@ -47,7 +47,8 @@ static struct cpufreq_governor cpufreq_gov_ondemand; static struct od_dbs_tuners od_tuners = { .up_threshold = DEF_FREQUENCY_UP_THRESHOLD, .sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR, - .down_differential = DEF_FREQUENCY_DOWN_DIFFERENTIAL, + .adj_up_threshold = DEF_FREQUENCY_UP_THRESHOLD - + DEF_FREQUENCY_DOWN_DIFFERENTIAL, .ignore_nice = 0, .powersave_bias = 0, }; @@ -65,7 +66,7 @@ static void ondemand_powersave_bias_init_cpu(int cpu) * efficient idling at a higher frequency/voltage is. * Pavel Machek says this is not so for various generations of AMD and old * Intel systems. - * Mike Chan (androidlcom) calis this is also not true for ARM. + * Mike Chan (android.com) claims this is also not true for ARM. * Because of this, whitelist specific known (series) of CPUs by default, and * leave all others up to the user. */ @@ -73,7 +74,7 @@ static int should_io_be_busy(void) { #if defined(CONFIG_X86) /* - * For Intel, Core 2 (model 15) andl later have an efficient idle. + * For Intel, Core 2 (model 15) and later have an efficient idle. */ if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && boot_cpu_data.x86 == 6 && @@ -158,8 +159,8 @@ static void dbs_freq_increase(struct cpufreq_policy *p, unsigned int freq) /* * Every sampling_rate, we check, if current idle time is less than 20% - * (default), then we try to increase frequency Every sampling_rate, we look for - * a the lowest frequency which can sustain the load while keeping idle time + * (default), then we try to increase frequency. Every sampling_rate, we look + * for the lowest frequency which can sustain the load while keeping idle time * over 30%. If such a frequency exist, we try to decrease to this frequency. * * Any frequency increase takes it to the maximum frequency. Frequency reduction @@ -192,11 +193,9 @@ static void od_check_cpu(int cpu, unsigned int load_freq) * support the current CPU usage without triggering the up policy. To be * safe, we focus 10 points under the threshold. */ - if (load_freq < (od_tuners.up_threshold - od_tuners.down_differential) * - policy->cur) { + if (load_freq < od_tuners.adj_up_threshold * policy->cur) { unsigned int freq_next; - freq_next = load_freq / (od_tuners.up_threshold - - od_tuners.down_differential); + freq_next = load_freq / od_tuners.adj_up_threshold; /* No longer fully busy, reset rate_mult */ dbs_info->rate_mult = 1; @@ -218,33 +217,42 @@ static void od_check_cpu(int cpu, unsigned int load_freq) static void od_dbs_timer(struct work_struct *work) { + struct delayed_work *dw = to_delayed_work(work); struct od_cpu_dbs_info_s *dbs_info = container_of(work, struct od_cpu_dbs_info_s, cdbs.work.work); - unsigned int cpu = dbs_info->cdbs.cpu; - int delay, sample_type = dbs_info->sample_type; + unsigned int cpu = dbs_info->cdbs.cur_policy->cpu; + struct od_cpu_dbs_info_s *core_dbs_info = &per_cpu(od_cpu_dbs_info, + cpu); + int delay, sample_type = core_dbs_info->sample_type; + bool eval_load; - mutex_lock(&dbs_info->cdbs.timer_mutex); + mutex_lock(&core_dbs_info->cdbs.timer_mutex); + eval_load = need_load_eval(&core_dbs_info->cdbs, + od_tuners.sampling_rate); /* Common NORMAL_SAMPLE setup */ - dbs_info->sample_type = OD_NORMAL_SAMPLE; + core_dbs_info->sample_type = OD_NORMAL_SAMPLE; if (sample_type == OD_SUB_SAMPLE) { - delay = dbs_info->freq_lo_jiffies; - __cpufreq_driver_target(dbs_info->cdbs.cur_policy, - dbs_info->freq_lo, CPUFREQ_RELATION_H); + delay = core_dbs_info->freq_lo_jiffies; + if (eval_load) + __cpufreq_driver_target(core_dbs_info->cdbs.cur_policy, + core_dbs_info->freq_lo, + CPUFREQ_RELATION_H); } else { - dbs_check_cpu(&od_dbs_data, cpu); - if (dbs_info->freq_lo) { + if (eval_load) + dbs_check_cpu(&od_dbs_data, cpu); + if (core_dbs_info->freq_lo) { /* Setup timer for SUB_SAMPLE */ - dbs_info->sample_type = OD_SUB_SAMPLE; - delay = dbs_info->freq_hi_jiffies; + core_dbs_info->sample_type = OD_SUB_SAMPLE; + delay = core_dbs_info->freq_hi_jiffies; } else { delay = delay_for_sampling_rate(od_tuners.sampling_rate - * dbs_info->rate_mult); + * core_dbs_info->rate_mult); } } - schedule_delayed_work_on(cpu, &dbs_info->cdbs.work, delay); - mutex_unlock(&dbs_info->cdbs.timer_mutex); + schedule_delayed_work_on(smp_processor_id(), dw, delay); + mutex_unlock(&core_dbs_info->cdbs.timer_mutex); } /************************** sysfs interface ************************/ @@ -259,7 +267,7 @@ static ssize_t show_sampling_rate_min(struct kobject *kobj, * update_sampling_rate - update sampling rate effective immediately if needed. * @new_rate: new sampling rate * - * If new rate is smaller than the old, simply updaing + * If new rate is smaller than the old, simply updating * dbs_tuners_int.sampling_rate might not be appropriate. For example, if the * original sampling_rate was 1 second and the requested new sampling rate is 10 * ms because the user needs immediate reaction from ondemand governor, but not @@ -287,7 +295,7 @@ static void update_sampling_rate(unsigned int new_rate) cpufreq_cpu_put(policy); continue; } - dbs_info = &per_cpu(od_cpu_dbs_info, policy->cpu); + dbs_info = &per_cpu(od_cpu_dbs_info, cpu); cpufreq_cpu_put(policy); mutex_lock(&dbs_info->cdbs.timer_mutex); @@ -306,8 +314,7 @@ static void update_sampling_rate(unsigned int new_rate) cancel_delayed_work_sync(&dbs_info->cdbs.work); mutex_lock(&dbs_info->cdbs.timer_mutex); - schedule_delayed_work_on(dbs_info->cdbs.cpu, - &dbs_info->cdbs.work, + schedule_delayed_work_on(cpu, &dbs_info->cdbs.work, usecs_to_jiffies(new_rate)); } @@ -351,6 +358,10 @@ static ssize_t store_up_threshold(struct kobject *a, struct attribute *b, input < MIN_FREQUENCY_UP_THRESHOLD) { return -EINVAL; } + /* Calculate the new adj_up_threshold */ + od_tuners.adj_up_threshold += input; + od_tuners.adj_up_threshold -= od_tuners.up_threshold; + od_tuners.up_threshold = input; return count; } @@ -507,7 +518,8 @@ static int __init cpufreq_gov_dbs_init(void) if (idle_time != -1ULL) { /* Idle micro accounting is supported. Use finer thresholds */ od_tuners.up_threshold = MICRO_FREQUENCY_UP_THRESHOLD; - od_tuners.down_differential = MICRO_FREQUENCY_DOWN_DIFFERENTIAL; + od_tuners.adj_up_threshold = MICRO_FREQUENCY_UP_THRESHOLD - + MICRO_FREQUENCY_DOWN_DIFFERENTIAL; /* * In nohz/micro accounting case we set the minimum frequency * not depending on HZ, but fixed (very low). The deferred diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index 9d7732b810445f6b73318e574924b6bed6ac6829..2fd779eb1ed1f9fcdb7cb70ab54ed319fe1e4160 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -24,12 +24,6 @@ static spinlock_t cpufreq_stats_lock; -#define CPUFREQ_STATDEVICE_ATTR(_name, _mode, _show) \ -static struct freq_attr _attr_##_name = {\ - .attr = {.name = __stringify(_name), .mode = _mode, }, \ - .show = _show,\ -}; - struct cpufreq_stats { unsigned int cpu; unsigned int total_trans; @@ -136,17 +130,17 @@ static ssize_t show_trans_table(struct cpufreq_policy *policy, char *buf) return PAGE_SIZE; return len; } -CPUFREQ_STATDEVICE_ATTR(trans_table, 0444, show_trans_table); +cpufreq_freq_attr_ro(trans_table); #endif -CPUFREQ_STATDEVICE_ATTR(total_trans, 0444, show_total_trans); -CPUFREQ_STATDEVICE_ATTR(time_in_state, 0444, show_time_in_state); +cpufreq_freq_attr_ro(total_trans); +cpufreq_freq_attr_ro(time_in_state); static struct attribute *default_attrs[] = { - &_attr_total_trans.attr, - &_attr_time_in_state.attr, + &total_trans.attr, + &time_in_state.attr, #ifdef CONFIG_CPU_FREQ_STAT_DETAILS - &_attr_trans_table.attr, + &trans_table.attr, #endif NULL }; @@ -170,11 +164,13 @@ static int freq_table_get_index(struct cpufreq_stats *stat, unsigned int freq) static void cpufreq_stats_free_table(unsigned int cpu) { struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, cpu); + if (stat) { + pr_debug("%s: Free stat table\n", __func__); kfree(stat->time_in_state); kfree(stat); + per_cpu(cpufreq_stats_table, cpu) = NULL; } - per_cpu(cpufreq_stats_table, cpu) = NULL; } /* must be called early in the CPU removal sequence (before @@ -183,8 +179,14 @@ static void cpufreq_stats_free_table(unsigned int cpu) static void cpufreq_stats_free_sysfs(unsigned int cpu) { struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); - if (policy && policy->cpu == cpu) + + if (!cpufreq_frequency_get_table(cpu)) + return; + + if (policy && !policy_is_shared(policy)) { + pr_debug("%s: Free sysfs stat\n", __func__); sysfs_remove_group(&policy->kobj, &stats_attr_group); + } if (policy) cpufreq_cpu_put(policy); } @@ -262,6 +264,19 @@ static int cpufreq_stats_create_table(struct cpufreq_policy *policy, return ret; } +static void cpufreq_stats_update_policy_cpu(struct cpufreq_policy *policy) +{ + struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, + policy->last_cpu); + + pr_debug("Updating stats_table for new_cpu %u from last_cpu %u\n", + policy->cpu, policy->last_cpu); + per_cpu(cpufreq_stats_table, policy->cpu) = per_cpu(cpufreq_stats_table, + policy->last_cpu); + per_cpu(cpufreq_stats_table, policy->last_cpu) = NULL; + stat->cpu = policy->cpu; +} + static int cpufreq_stat_notifier_policy(struct notifier_block *nb, unsigned long val, void *data) { @@ -269,6 +284,12 @@ static int cpufreq_stat_notifier_policy(struct notifier_block *nb, struct cpufreq_policy *policy = data; struct cpufreq_frequency_table *table; unsigned int cpu = policy->cpu; + + if (val == CPUFREQ_UPDATE_POLICY_CPU) { + cpufreq_stats_update_policy_cpu(policy); + return 0; + } + if (val != CPUFREQ_NOTIFY) return 0; table = cpufreq_frequency_get_table(cpu); diff --git a/drivers/cpufreq/cpufreq_userspace.c b/drivers/cpufreq/cpufreq_userspace.c index c8c3d293cc57239c1f7d1965000a64c183204de1..bbeb9c0720a665ead5c76462d2f8882461f48e95 100644 --- a/drivers/cpufreq/cpufreq_userspace.c +++ b/drivers/cpufreq/cpufreq_userspace.c @@ -118,8 +118,6 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy, switch (event) { case CPUFREQ_GOV_START: - if (!cpu_online(cpu)) - return -EINVAL; BUG_ON(!policy->cur); mutex_lock(&userspace_mutex); diff --git a/drivers/cpufreq/db8500-cpufreq.c b/drivers/cpufreq/db8500-cpufreq.c index 4f154bc0ebe493b7d5b2b95374ee920927ccf77a..79a84860ea56e3a5b119b4181d512fddbb7e93cb 100644 --- a/drivers/cpufreq/db8500-cpufreq.c +++ b/drivers/cpufreq/db8500-cpufreq.c @@ -128,9 +128,7 @@ static int __cpuinit db8500_cpufreq_init(struct cpufreq_policy *policy) policy->cpuinfo.transition_latency = 20 * 1000; /* in ns */ /* policy sharing between dual CPUs */ - cpumask_copy(policy->cpus, cpu_present_mask); - - policy->shared_type = CPUFREQ_SHARED_TYPE_ALL; + cpumask_setall(policy->cpus); return 0; } diff --git a/drivers/cpufreq/exynos-cpufreq.c b/drivers/cpufreq/exynos-cpufreq.c index 7012ea8bf1e736aa82d9cd464429e41e7cfb1e70..69b676dd3358e2c806cf1587cad6d2215e1e9a4e 100644 --- a/drivers/cpufreq/exynos-cpufreq.c +++ b/drivers/cpufreq/exynos-cpufreq.c @@ -42,51 +42,56 @@ static unsigned int exynos_getspeed(unsigned int cpu) return clk_get_rate(exynos_info->cpu_clk) / 1000; } -static int exynos_target(struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) +static int exynos_cpufreq_get_index(unsigned int freq) +{ + struct cpufreq_frequency_table *freq_table = exynos_info->freq_table; + int index; + + for (index = 0; + freq_table[index].frequency != CPUFREQ_TABLE_END; index++) + if (freq_table[index].frequency == freq) + break; + + if (freq_table[index].frequency == CPUFREQ_TABLE_END) + return -EINVAL; + + return index; +} + +static int exynos_cpufreq_scale(unsigned int target_freq) { - unsigned int index, old_index; - unsigned int arm_volt, safe_arm_volt = 0; - int ret = 0; struct cpufreq_frequency_table *freq_table = exynos_info->freq_table; unsigned int *volt_table = exynos_info->volt_table; + struct cpufreq_policy *policy = cpufreq_cpu_get(0); + unsigned int arm_volt, safe_arm_volt = 0; unsigned int mpll_freq_khz = exynos_info->mpll_freq_khz; - - mutex_lock(&cpufreq_lock); + int index, old_index; + int ret = 0; freqs.old = policy->cur; + freqs.new = target_freq; + freqs.cpu = policy->cpu; - if (frequency_locked && target_freq != locking_frequency) { - ret = -EAGAIN; + if (freqs.new == freqs.old) goto out; - } /* * The policy max have been changed so that we cannot get proper * old_index with cpufreq_frequency_table_target(). Thus, ignore * policy and get the index from the raw freqeuncy table. */ - for (old_index = 0; - freq_table[old_index].frequency != CPUFREQ_TABLE_END; - old_index++) - if (freq_table[old_index].frequency == freqs.old) - break; - - if (freq_table[old_index].frequency == CPUFREQ_TABLE_END) { - ret = -EINVAL; + old_index = exynos_cpufreq_get_index(freqs.old); + if (old_index < 0) { + ret = old_index; goto out; } - if (cpufreq_frequency_table_target(policy, freq_table, - target_freq, relation, &index)) { - ret = -EINVAL; + index = exynos_cpufreq_get_index(target_freq); + if (index < 0) { + ret = index; goto out; } - freqs.new = freq_table[index].frequency; - freqs.cpu = policy->cpu; - /* * ARM clock source will be changed APLL to MPLL temporary * To support this level, need to control regulator for @@ -106,15 +111,25 @@ static int exynos_target(struct cpufreq_policy *policy, /* When the new frequency is higher than current frequency */ if ((freqs.new > freqs.old) && !safe_arm_volt) { /* Firstly, voltage up to increase frequency */ - regulator_set_voltage(arm_regulator, arm_volt, - 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", + __func__, arm_volt); + goto out; + } } - if (safe_arm_volt) - regulator_set_voltage(arm_regulator, safe_arm_volt, + if (safe_arm_volt) { + ret = regulator_set_voltage(arm_regulator, safe_arm_volt, safe_arm_volt); - if (freqs.new != freqs.old) - exynos_info->set_freq(old_index, index); + if (ret) { + pr_err("%s: failed to set cpu voltage to %d\n", + __func__, safe_arm_volt); + goto out; + } + } + + exynos_info->set_freq(old_index, index); for_each_cpu(freqs.cpu, policy->cpus) cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); @@ -125,8 +140,44 @@ static int exynos_target(struct cpufreq_policy *policy, /* down the voltage after frequency change */ regulator_set_voltage(arm_regulator, arm_volt, arm_volt); + if (ret) { + pr_err("%s: failed to set cpu voltage to %d\n", + __func__, arm_volt); + goto out; + } + } + +out: + + cpufreq_cpu_put(policy); + + return ret; +} + +static int exynos_target(struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) +{ + struct cpufreq_frequency_table *freq_table = exynos_info->freq_table; + unsigned int index; + unsigned int new_freq; + int ret = 0; + + mutex_lock(&cpufreq_lock); + + if (frequency_locked) + goto out; + + if (cpufreq_frequency_table_target(policy, freq_table, + target_freq, relation, &index)) { + ret = -EINVAL; + goto out; } + new_freq = freq_table[index].frequency; + + ret = exynos_cpufreq_scale(new_freq); + out: mutex_unlock(&cpufreq_lock); @@ -163,51 +214,26 @@ static int exynos_cpufreq_resume(struct cpufreq_policy *policy) static int exynos_cpufreq_pm_notifier(struct notifier_block *notifier, unsigned long pm_event, void *v) { - struct cpufreq_policy *policy = cpufreq_cpu_get(0); /* boot CPU */ - static unsigned int saved_frequency; - unsigned int temp; + int ret; - mutex_lock(&cpufreq_lock); switch (pm_event) { case PM_SUSPEND_PREPARE: - if (frequency_locked) - goto out; - + mutex_lock(&cpufreq_lock); frequency_locked = true; + mutex_unlock(&cpufreq_lock); - if (locking_frequency) { - saved_frequency = exynos_getspeed(0); + ret = exynos_cpufreq_scale(locking_frequency); + if (ret < 0) + return NOTIFY_BAD; - mutex_unlock(&cpufreq_lock); - exynos_target(policy, locking_frequency, - CPUFREQ_RELATION_H); - mutex_lock(&cpufreq_lock); - } break; case PM_POST_SUSPEND: - if (saved_frequency) { - /* - * While frequency_locked, only locking_frequency - * is valid for target(). In order to use - * saved_frequency while keeping frequency_locked, - * we temporarly overwrite locking_frequency. - */ - temp = locking_frequency; - locking_frequency = saved_frequency; - - mutex_unlock(&cpufreq_lock); - exynos_target(policy, locking_frequency, - CPUFREQ_RELATION_H); - mutex_lock(&cpufreq_lock); - - locking_frequency = temp; - } + mutex_lock(&cpufreq_lock); frequency_locked = false; + mutex_unlock(&cpufreq_lock); break; } -out: - mutex_unlock(&cpufreq_lock); return NOTIFY_OK; } @@ -222,35 +248,34 @@ static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy) cpufreq_frequency_table_get_attr(exynos_info->freq_table, policy->cpu); - locking_frequency = exynos_getspeed(0); - /* set the transition latency value */ policy->cpuinfo.transition_latency = 100000; - /* - * EXYNOS4 multi-core processors has 2 cores - * that the frequency cannot be set independently. - * Each cpu is bound to the same speed. - * So the affected cpu is all of the cpus. - */ - if (num_online_cpus() == 1) { - cpumask_copy(policy->related_cpus, cpu_possible_mask); - cpumask_copy(policy->cpus, cpu_online_mask); - } else { - policy->shared_type = CPUFREQ_SHARED_TYPE_ANY; - cpumask_setall(policy->cpus); - } + cpumask_setall(policy->cpus); return cpufreq_frequency_table_cpuinfo(policy, exynos_info->freq_table); } +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, .target = exynos_target, .get = exynos_getspeed, .init = exynos_cpufreq_cpu_init, + .exit = exynos_cpufreq_cpu_exit, .name = "exynos_cpufreq", + .attr = exynos_cpufreq_attr, #ifdef CONFIG_PM .suspend = exynos_cpufreq_suspend, .resume = exynos_cpufreq_resume, @@ -288,6 +313,8 @@ static int __init exynos_cpufreq_init(void) goto err_vdd_arm; } + locking_frequency = exynos_getspeed(0); + register_pm_notifier(&exynos_cpufreq_nb); if (cpufreq_register_driver(&exynos_driver)) { @@ -299,8 +326,7 @@ static int __init exynos_cpufreq_init(void) err_cpufreq: unregister_pm_notifier(&exynos_cpufreq_nb); - if (!IS_ERR(arm_regulator)) - regulator_put(arm_regulator); + regulator_put(arm_regulator); err_vdd_arm: kfree(exynos_info); pr_debug("%s: failed initialization\n", __func__); diff --git a/drivers/cpufreq/exynos4210-cpufreq.c b/drivers/cpufreq/exynos4210-cpufreq.c index fb148fa276781ef40d4844c7d4d686b1ee801a8b..de91755e2556b0311d9da8327d7db4f7803b49af 100644 --- a/drivers/cpufreq/exynos4210-cpufreq.c +++ b/drivers/cpufreq/exynos4210-cpufreq.c @@ -20,97 +20,37 @@ #include #include -#define CPUFREQ_LEVEL_END L5 - -static int max_support_idx = L0; -static int min_support_idx = (CPUFREQ_LEVEL_END - 1); - static struct clk *cpu_clk; static struct clk *moutcore; static struct clk *mout_mpll; static struct clk *mout_apll; -struct cpufreq_clkdiv { - unsigned int index; - unsigned int clkdiv; -}; - -static unsigned int exynos4210_volt_table[CPUFREQ_LEVEL_END] = { +static unsigned int exynos4210_volt_table[] = { 1250000, 1150000, 1050000, 975000, 950000, }; - -static struct cpufreq_clkdiv exynos4210_clkdiv_table[CPUFREQ_LEVEL_END]; - static struct cpufreq_frequency_table exynos4210_freq_table[] = { - {L0, 1200*1000}, - {L1, 1000*1000}, - {L2, 800*1000}, - {L3, 500*1000}, - {L4, 200*1000}, + {L0, 1200 * 1000}, + {L1, 1000 * 1000}, + {L2, 800 * 1000}, + {L3, 500 * 1000}, + {L4, 200 * 1000}, {0, CPUFREQ_TABLE_END}, }; -static unsigned int clkdiv_cpu0[CPUFREQ_LEVEL_END][7] = { +static struct apll_freq apll_freq_4210[] = { /* - * Clock divider value for following - * { DIVCORE, DIVCOREM0, DIVCOREM1, DIVPERIPH, - * DIVATB, DIVPCLK_DBG, DIVAPLL } + * values: + * freq + * clock divider for CORE, COREM0, COREM1, PERIPH, ATB, PCLK_DBG, APLL, RESERVED + * clock divider for COPY, HPM, RESERVED + * PLL M, P, S */ - - /* ARM L0: 1200MHz */ - { 0, 3, 7, 3, 4, 1, 7 }, - - /* ARM L1: 1000MHz */ - { 0, 3, 7, 3, 4, 1, 7 }, - - /* ARM L2: 800MHz */ - { 0, 3, 7, 3, 3, 1, 7 }, - - /* ARM L3: 500MHz */ - { 0, 3, 7, 3, 3, 1, 7 }, - - /* ARM L4: 200MHz */ - { 0, 1, 3, 1, 3, 1, 0 }, -}; - -static unsigned int clkdiv_cpu1[CPUFREQ_LEVEL_END][2] = { - /* - * Clock divider value for following - * { DIVCOPY, DIVHPM } - */ - - /* ARM L0: 1200MHz */ - { 5, 0 }, - - /* ARM L1: 1000MHz */ - { 4, 0 }, - - /* ARM L2: 800MHz */ - { 3, 0 }, - - /* ARM L3: 500MHz */ - { 3, 0 }, - - /* ARM L4: 200MHz */ - { 3, 0 }, -}; - -static unsigned int exynos4210_apll_pms_table[CPUFREQ_LEVEL_END] = { - /* APLL FOUT L0: 1200MHz */ - ((150 << 16) | (3 << 8) | 1), - - /* APLL FOUT L1: 1000MHz */ - ((250 << 16) | (6 << 8) | 1), - - /* APLL FOUT L2: 800MHz */ - ((200 << 16) | (6 << 8) | 1), - - /* APLL FOUT L3: 500MHz */ - ((250 << 16) | (6 << 8) | 2), - - /* APLL FOUT L4: 200MHz */ - ((200 << 16) | (6 << 8) | 3), + APLL_FREQ(1200, 0, 3, 7, 3, 4, 1, 7, 0, 5, 0, 0, 150, 3, 1), + APLL_FREQ(1000, 0, 3, 7, 3, 4, 1, 7, 0, 4, 0, 0, 250, 6, 1), + APLL_FREQ(800, 0, 3, 7, 3, 3, 1, 7, 0, 3, 0, 0, 200, 6, 1), + APLL_FREQ(500, 0, 3, 7, 3, 3, 1, 7, 0, 3, 0, 0, 250, 6, 2), + APLL_FREQ(200, 0, 1, 3, 1, 3, 1, 0, 0, 3, 0, 0, 200, 6, 3), }; static void exynos4210_set_clkdiv(unsigned int div_index) @@ -119,7 +59,7 @@ static void exynos4210_set_clkdiv(unsigned int div_index) /* Change Divider - CPU0 */ - tmp = exynos4210_clkdiv_table[div_index].clkdiv; + tmp = apll_freq_4210[div_index].clk_div_cpu0; __raw_writel(tmp, EXYNOS4_CLKDIV_CPU); @@ -129,12 +69,7 @@ static void exynos4210_set_clkdiv(unsigned int div_index) /* Change Divider - CPU1 */ - tmp = __raw_readl(EXYNOS4_CLKDIV_CPU1); - - tmp &= ~((0x7 << 4) | 0x7); - - tmp |= ((clkdiv_cpu1[div_index][0] << 4) | - (clkdiv_cpu1[div_index][1] << 0)); + tmp = apll_freq_4210[div_index].clk_div_cpu1; __raw_writel(tmp, EXYNOS4_CLKDIV_CPU1); @@ -162,7 +97,7 @@ static void exynos4210_set_apll(unsigned int index) /* 3. Change PLL PMS values */ tmp = __raw_readl(EXYNOS4_APLL_CON0); tmp &= ~((0x3ff << 16) | (0x3f << 8) | (0x7 << 0)); - tmp |= exynos4210_apll_pms_table[index]; + tmp |= apll_freq_4210[index].mps; __raw_writel(tmp, EXYNOS4_APLL_CON0); /* 4. wait_lock_time */ @@ -179,10 +114,10 @@ static void exynos4210_set_apll(unsigned int index) } while (tmp != (0x1 << EXYNOS4_CLKSRC_CPU_MUXCORE_SHIFT)); } -bool exynos4210_pms_change(unsigned int old_index, unsigned int new_index) +static bool exynos4210_pms_change(unsigned int old_index, unsigned int new_index) { - unsigned int old_pm = (exynos4210_apll_pms_table[old_index] >> 8); - unsigned int new_pm = (exynos4210_apll_pms_table[new_index] >> 8); + 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; } @@ -200,7 +135,7 @@ static void exynos4210_set_frequency(unsigned int old_index, /* 2. Change just s value in apll m,p,s value */ tmp = __raw_readl(EXYNOS4_APLL_CON0); tmp &= ~(0x7 << 0); - tmp |= (exynos4210_apll_pms_table[new_index] & 0x7); + tmp |= apll_freq_4210[new_index].mps & 0x7; __raw_writel(tmp, EXYNOS4_APLL_CON0); } else { /* Clock Configuration Procedure */ @@ -214,7 +149,7 @@ static void exynos4210_set_frequency(unsigned int old_index, /* 1. Change just s value in apll m,p,s value */ tmp = __raw_readl(EXYNOS4_APLL_CON0); tmp &= ~(0x7 << 0); - tmp |= (exynos4210_apll_pms_table[new_index] & 0x7); + tmp |= apll_freq_4210[new_index].mps & 0x7; __raw_writel(tmp, EXYNOS4_APLL_CON0); /* 2. Change the system clock divider values */ @@ -231,8 +166,6 @@ static void exynos4210_set_frequency(unsigned int old_index, int exynos4210_cpufreq_init(struct exynos_dvfs_info *info) { - int i; - unsigned int tmp; unsigned long rate; cpu_clk = clk_get(NULL, "armclk"); @@ -253,33 +186,9 @@ int exynos4210_cpufreq_init(struct exynos_dvfs_info *info) if (IS_ERR(mout_apll)) goto err_mout_apll; - tmp = __raw_readl(EXYNOS4_CLKDIV_CPU); - - for (i = L0; i < CPUFREQ_LEVEL_END; i++) { - tmp &= ~(EXYNOS4_CLKDIV_CPU0_CORE_MASK | - EXYNOS4_CLKDIV_CPU0_COREM0_MASK | - EXYNOS4_CLKDIV_CPU0_COREM1_MASK | - EXYNOS4_CLKDIV_CPU0_PERIPH_MASK | - EXYNOS4_CLKDIV_CPU0_ATB_MASK | - EXYNOS4_CLKDIV_CPU0_PCLKDBG_MASK | - EXYNOS4_CLKDIV_CPU0_APLL_MASK); - - tmp |= ((clkdiv_cpu0[i][0] << EXYNOS4_CLKDIV_CPU0_CORE_SHIFT) | - (clkdiv_cpu0[i][1] << EXYNOS4_CLKDIV_CPU0_COREM0_SHIFT) | - (clkdiv_cpu0[i][2] << EXYNOS4_CLKDIV_CPU0_COREM1_SHIFT) | - (clkdiv_cpu0[i][3] << EXYNOS4_CLKDIV_CPU0_PERIPH_SHIFT) | - (clkdiv_cpu0[i][4] << EXYNOS4_CLKDIV_CPU0_ATB_SHIFT) | - (clkdiv_cpu0[i][5] << EXYNOS4_CLKDIV_CPU0_PCLKDBG_SHIFT) | - (clkdiv_cpu0[i][6] << EXYNOS4_CLKDIV_CPU0_APLL_SHIFT)); - - exynos4210_clkdiv_table[i].clkdiv = tmp; - } - info->mpll_freq_khz = rate; - info->pm_lock_idx = L2; + /* 800Mhz */ info->pll_safe_idx = L2; - info->max_support_idx = max_support_idx; - info->min_support_idx = min_support_idx; info->cpu_clk = cpu_clk; info->volt_table = exynos4210_volt_table; info->freq_table = exynos4210_freq_table; @@ -289,14 +198,11 @@ int exynos4210_cpufreq_init(struct exynos_dvfs_info *info) return 0; err_mout_apll: - if (!IS_ERR(mout_mpll)) - clk_put(mout_mpll); + clk_put(mout_mpll); err_mout_mpll: - if (!IS_ERR(moutcore)) - clk_put(moutcore); + clk_put(moutcore); err_moutcore: - if (!IS_ERR(cpu_clk)) - clk_put(cpu_clk); + clk_put(cpu_clk); pr_debug("%s: failed initialization\n", __func__); return -EINVAL; diff --git a/drivers/cpufreq/exynos4x12-cpufreq.c b/drivers/cpufreq/exynos4x12-cpufreq.c index 8c5a7afa5b0b0d818e25f098707c84f377de7532..0661039e5d4a709d6422f76fd819c7b45be0785e 100644 --- a/drivers/cpufreq/exynos4x12-cpufreq.c +++ b/drivers/cpufreq/exynos4x12-cpufreq.c @@ -20,26 +20,18 @@ #include #include -#define CPUFREQ_LEVEL_END (L13 + 1) - -static int max_support_idx; -static int min_support_idx = (CPUFREQ_LEVEL_END - 1); - static struct clk *cpu_clk; static struct clk *moutcore; static struct clk *mout_mpll; static struct clk *mout_apll; -struct cpufreq_clkdiv { - unsigned int index; - unsigned int clkdiv; - unsigned int clkdiv1; +static unsigned int exynos4x12_volt_table[] = { + 1350000, 1287500, 1250000, 1187500, 1137500, 1087500, 1037500, + 1000000, 987500, 975000, 950000, 925000, 900000, 900000 }; -static unsigned int exynos4x12_volt_table[CPUFREQ_LEVEL_END]; - static struct cpufreq_frequency_table exynos4x12_freq_table[] = { - {L0, 1500 * 1000}, + {L0, CPUFREQ_ENTRY_INVALID}, {L1, 1400 * 1000}, {L2, 1300 * 1000}, {L3, 1200 * 1000}, @@ -56,247 +48,54 @@ static struct cpufreq_frequency_table exynos4x12_freq_table[] = { {0, CPUFREQ_TABLE_END}, }; -static struct cpufreq_clkdiv exynos4x12_clkdiv_table[CPUFREQ_LEVEL_END]; +static struct apll_freq *apll_freq_4x12; -static unsigned int clkdiv_cpu0_4212[CPUFREQ_LEVEL_END][8] = { +static struct apll_freq apll_freq_4212[] = { /* - * Clock divider value for following - * { DIVCORE, DIVCOREM0, DIVCOREM1, DIVPERIPH, - * DIVATB, DIVPCLK_DBG, DIVAPLL, DIVCORE2 } + * values: + * freq + * clock divider for CORE, COREM0, COREM1, PERIPH, ATB, PCLK_DBG, APLL, CORE2 + * clock divider for COPY, HPM, RESERVED + * PLL M, P, S */ - /* ARM L0: 1500 MHz */ - { 0, 3, 7, 0, 6, 1, 2, 0 }, - - /* ARM L1: 1400 MHz */ - { 0, 3, 7, 0, 6, 1, 2, 0 }, - - /* ARM L2: 1300 MHz */ - { 0, 3, 7, 0, 5, 1, 2, 0 }, - - /* ARM L3: 1200 MHz */ - { 0, 3, 7, 0, 5, 1, 2, 0 }, - - /* ARM L4: 1100 MHz */ - { 0, 3, 6, 0, 4, 1, 2, 0 }, - - /* ARM L5: 1000 MHz */ - { 0, 2, 5, 0, 4, 1, 1, 0 }, - - /* ARM L6: 900 MHz */ - { 0, 2, 5, 0, 3, 1, 1, 0 }, - - /* ARM L7: 800 MHz */ - { 0, 2, 5, 0, 3, 1, 1, 0 }, - - /* ARM L8: 700 MHz */ - { 0, 2, 4, 0, 3, 1, 1, 0 }, - - /* ARM L9: 600 MHz */ - { 0, 2, 4, 0, 3, 1, 1, 0 }, - - /* ARM L10: 500 MHz */ - { 0, 2, 4, 0, 3, 1, 1, 0 }, - - /* ARM L11: 400 MHz */ - { 0, 2, 4, 0, 3, 1, 1, 0 }, - - /* ARM L12: 300 MHz */ - { 0, 2, 4, 0, 2, 1, 1, 0 }, - - /* ARM L13: 200 MHz */ - { 0, 1, 3, 0, 1, 1, 1, 0 }, + APLL_FREQ(1500, 0, 3, 7, 0, 6, 1, 2, 0, 6, 2, 0, 250, 4, 0), + APLL_FREQ(1400, 0, 3, 7, 0, 6, 1, 2, 0, 6, 2, 0, 175, 3, 0), + APLL_FREQ(1300, 0, 3, 7, 0, 5, 1, 2, 0, 5, 2, 0, 325, 6, 0), + APLL_FREQ(1200, 0, 3, 7, 0, 5, 1, 2, 0, 5, 2, 0, 200, 4, 0), + APLL_FREQ(1100, 0, 3, 6, 0, 4, 1, 2, 0, 4, 2, 0, 275, 6, 0), + APLL_FREQ(1000, 0, 2, 5, 0, 4, 1, 1, 0, 4, 2, 0, 125, 3, 0), + APLL_FREQ(900, 0, 2, 5, 0, 3, 1, 1, 0, 3, 2, 0, 150, 4, 0), + APLL_FREQ(800, 0, 2, 5, 0, 3, 1, 1, 0, 3, 2, 0, 100, 3, 0), + APLL_FREQ(700, 0, 2, 4, 0, 3, 1, 1, 0, 3, 2, 0, 175, 3, 1), + APLL_FREQ(600, 0, 2, 4, 0, 3, 1, 1, 0, 3, 2, 0, 200, 4, 1), + APLL_FREQ(500, 0, 2, 4, 0, 3, 1, 1, 0, 3, 2, 0, 125, 3, 1), + APLL_FREQ(400, 0, 2, 4, 0, 3, 1, 1, 0, 3, 2, 0, 100, 3, 1), + APLL_FREQ(300, 0, 2, 4, 0, 2, 1, 1, 0, 3, 2, 0, 200, 4, 2), + APLL_FREQ(200, 0, 1, 3, 0, 1, 1, 1, 0, 3, 2, 0, 100, 3, 2), }; -static unsigned int clkdiv_cpu0_4412[CPUFREQ_LEVEL_END][8] = { +static struct apll_freq apll_freq_4412[] = { /* - * Clock divider value for following - * { DIVCORE, DIVCOREM0, DIVCOREM1, DIVPERIPH, - * DIVATB, DIVPCLK_DBG, DIVAPLL, DIVCORE2 } - */ - /* ARM L0: 1500 MHz */ - { 0, 3, 7, 0, 6, 1, 2, 0 }, - - /* ARM L1: 1400 MHz */ - { 0, 3, 7, 0, 6, 1, 2, 0 }, - - /* ARM L2: 1300 MHz */ - { 0, 3, 7, 0, 5, 1, 2, 0 }, - - /* ARM L3: 1200 MHz */ - { 0, 3, 7, 0, 5, 1, 2, 0 }, - - /* ARM L4: 1100 MHz */ - { 0, 3, 6, 0, 4, 1, 2, 0 }, - - /* ARM L5: 1000 MHz */ - { 0, 2, 5, 0, 4, 1, 1, 0 }, - - /* ARM L6: 900 MHz */ - { 0, 2, 5, 0, 3, 1, 1, 0 }, - - /* ARM L7: 800 MHz */ - { 0, 2, 5, 0, 3, 1, 1, 0 }, - - /* ARM L8: 700 MHz */ - { 0, 2, 4, 0, 3, 1, 1, 0 }, - - /* ARM L9: 600 MHz */ - { 0, 2, 4, 0, 3, 1, 1, 0 }, - - /* ARM L10: 500 MHz */ - { 0, 2, 4, 0, 3, 1, 1, 0 }, - - /* ARM L11: 400 MHz */ - { 0, 2, 4, 0, 3, 1, 1, 0 }, - - /* ARM L12: 300 MHz */ - { 0, 2, 4, 0, 2, 1, 1, 0 }, - - /* ARM L13: 200 MHz */ - { 0, 1, 3, 0, 1, 1, 1, 0 }, -}; - -static unsigned int clkdiv_cpu1_4212[CPUFREQ_LEVEL_END][2] = { - /* Clock divider value for following - * { DIVCOPY, DIVHPM } - */ - /* ARM L0: 1500 MHz */ - { 6, 0 }, - - /* ARM L1: 1400 MHz */ - { 6, 0 }, - - /* ARM L2: 1300 MHz */ - { 5, 0 }, - - /* ARM L3: 1200 MHz */ - { 5, 0 }, - - /* ARM L4: 1100 MHz */ - { 4, 0 }, - - /* ARM L5: 1000 MHz */ - { 4, 0 }, - - /* ARM L6: 900 MHz */ - { 3, 0 }, - - /* ARM L7: 800 MHz */ - { 3, 0 }, - - /* ARM L8: 700 MHz */ - { 3, 0 }, - - /* ARM L9: 600 MHz */ - { 3, 0 }, - - /* ARM L10: 500 MHz */ - { 3, 0 }, - - /* ARM L11: 400 MHz */ - { 3, 0 }, - - /* ARM L12: 300 MHz */ - { 3, 0 }, - - /* ARM L13: 200 MHz */ - { 3, 0 }, -}; - -static unsigned int clkdiv_cpu1_4412[CPUFREQ_LEVEL_END][3] = { - /* Clock divider value for following - * { DIVCOPY, DIVHPM, DIVCORES } + * values: + * freq + * clock divider for CORE, COREM0, COREM1, PERIPH, ATB, PCLK_DBG, APLL, CORE2 + * clock divider for COPY, HPM, CORES + * PLL M, P, S */ - /* ARM L0: 1500 MHz */ - { 6, 0, 7 }, - - /* ARM L1: 1400 MHz */ - { 6, 0, 6 }, - - /* ARM L2: 1300 MHz */ - { 5, 0, 6 }, - - /* ARM L3: 1200 MHz */ - { 5, 0, 5 }, - - /* ARM L4: 1100 MHz */ - { 4, 0, 5 }, - - /* ARM L5: 1000 MHz */ - { 4, 0, 4 }, - - /* ARM L6: 900 MHz */ - { 3, 0, 4 }, - - /* ARM L7: 800 MHz */ - { 3, 0, 3 }, - - /* ARM L8: 700 MHz */ - { 3, 0, 3 }, - - /* ARM L9: 600 MHz */ - { 3, 0, 2 }, - - /* ARM L10: 500 MHz */ - { 3, 0, 2 }, - - /* ARM L11: 400 MHz */ - { 3, 0, 1 }, - - /* ARM L12: 300 MHz */ - { 3, 0, 1 }, - - /* ARM L13: 200 MHz */ - { 3, 0, 0 }, -}; - -static unsigned int exynos4x12_apll_pms_table[CPUFREQ_LEVEL_END] = { - /* APLL FOUT L0: 1500 MHz */ - ((250 << 16) | (4 << 8) | (0x0)), - - /* APLL FOUT L1: 1400 MHz */ - ((175 << 16) | (3 << 8) | (0x0)), - - /* APLL FOUT L2: 1300 MHz */ - ((325 << 16) | (6 << 8) | (0x0)), - - /* APLL FOUT L3: 1200 MHz */ - ((200 << 16) | (4 << 8) | (0x0)), - - /* APLL FOUT L4: 1100 MHz */ - ((275 << 16) | (6 << 8) | (0x0)), - - /* APLL FOUT L5: 1000 MHz */ - ((125 << 16) | (3 << 8) | (0x0)), - - /* APLL FOUT L6: 900 MHz */ - ((150 << 16) | (4 << 8) | (0x0)), - - /* APLL FOUT L7: 800 MHz */ - ((100 << 16) | (3 << 8) | (0x0)), - - /* APLL FOUT L8: 700 MHz */ - ((175 << 16) | (3 << 8) | (0x1)), - - /* APLL FOUT L9: 600 MHz */ - ((200 << 16) | (4 << 8) | (0x1)), - - /* APLL FOUT L10: 500 MHz */ - ((125 << 16) | (3 << 8) | (0x1)), - - /* APLL FOUT L11 400 MHz */ - ((100 << 16) | (3 << 8) | (0x1)), - - /* APLL FOUT L12: 300 MHz */ - ((200 << 16) | (4 << 8) | (0x2)), - - /* APLL FOUT L13: 200 MHz */ - ((100 << 16) | (3 << 8) | (0x2)), -}; - -static const unsigned int asv_voltage_4x12[CPUFREQ_LEVEL_END] = { - 1350000, 1287500, 1250000, 1187500, 1137500, 1087500, 1037500, - 1000000, 987500, 975000, 950000, 925000, 900000, 900000 + APLL_FREQ(1500, 0, 3, 7, 0, 6, 1, 2, 0, 6, 0, 7, 250, 4, 0), + APLL_FREQ(1400, 0, 3, 7, 0, 6, 1, 2, 0, 6, 0, 6, 175, 3, 0), + APLL_FREQ(1300, 0, 3, 7, 0, 5, 1, 2, 0, 5, 0, 6, 325, 6, 0), + APLL_FREQ(1200, 0, 3, 7, 0, 5, 1, 2, 0, 5, 0, 5, 200, 4, 0), + APLL_FREQ(1100, 0, 3, 6, 0, 4, 1, 2, 0, 4, 0, 5, 275, 6, 0), + APLL_FREQ(1000, 0, 2, 5, 0, 4, 1, 1, 0, 4, 0, 4, 125, 3, 0), + APLL_FREQ(900, 0, 2, 5, 0, 3, 1, 1, 0, 3, 0, 4, 150, 4, 0), + APLL_FREQ(800, 0, 2, 5, 0, 3, 1, 1, 0, 3, 0, 3, 100, 3, 0), + APLL_FREQ(700, 0, 2, 4, 0, 3, 1, 1, 0, 3, 0, 3, 175, 3, 1), + APLL_FREQ(600, 0, 2, 4, 0, 3, 1, 1, 0, 3, 0, 2, 200, 4, 1), + APLL_FREQ(500, 0, 2, 4, 0, 3, 1, 1, 0, 3, 0, 2, 125, 3, 1), + APLL_FREQ(400, 0, 2, 4, 0, 3, 1, 1, 0, 3, 0, 1, 100, 3, 1), + APLL_FREQ(300, 0, 2, 4, 0, 2, 1, 1, 0, 3, 0, 1, 200, 4, 2), + APLL_FREQ(200, 0, 1, 3, 0, 1, 1, 1, 0, 3, 0, 0, 100, 3, 2), }; static void exynos4x12_set_clkdiv(unsigned int div_index) @@ -306,7 +105,7 @@ static void exynos4x12_set_clkdiv(unsigned int div_index) /* Change Divider - CPU0 */ - tmp = exynos4x12_clkdiv_table[div_index].clkdiv; + tmp = apll_freq_4x12[div_index].clk_div_cpu0; __raw_writel(tmp, EXYNOS4_CLKDIV_CPU); @@ -314,7 +113,7 @@ static void exynos4x12_set_clkdiv(unsigned int div_index) cpu_relax(); /* Change Divider - CPU1 */ - tmp = exynos4x12_clkdiv_table[div_index].clkdiv1; + tmp = apll_freq_4x12[div_index].clk_div_cpu1; __raw_writel(tmp, EXYNOS4_CLKDIV_CPU1); if (soc_is_exynos4212()) @@ -341,14 +140,14 @@ static void exynos4x12_set_apll(unsigned int index) } while (tmp != 0x2); /* 2. Set APLL Lock time */ - pdiv = ((exynos4x12_apll_pms_table[index] >> 8) & 0x3f); + pdiv = ((apll_freq_4x12[index].mps >> 8) & 0x3f); __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 |= exynos4x12_apll_pms_table[index]; + tmp |= apll_freq_4x12[index].mps; __raw_writel(tmp, EXYNOS4_APLL_CON0); /* 4. wait_lock_time */ @@ -367,10 +166,10 @@ static void exynos4x12_set_apll(unsigned int index) } while (tmp != (0x1 << EXYNOS4_CLKSRC_CPU_MUXCORE_SHIFT)); } -bool exynos4x12_pms_change(unsigned int old_index, unsigned int new_index) +static bool exynos4x12_pms_change(unsigned int old_index, unsigned int new_index) { - unsigned int old_pm = exynos4x12_apll_pms_table[old_index] >> 8; - unsigned int new_pm = exynos4x12_apll_pms_table[new_index] >> 8; + 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; } @@ -387,7 +186,7 @@ static void exynos4x12_set_frequency(unsigned int old_index, /* 2. Change just s value in apll m,p,s value */ tmp = __raw_readl(EXYNOS4_APLL_CON0); tmp &= ~(0x7 << 0); - tmp |= (exynos4x12_apll_pms_table[new_index] & 0x7); + tmp |= apll_freq_4x12[new_index].mps & 0x7; __raw_writel(tmp, EXYNOS4_APLL_CON0); } else { @@ -402,7 +201,7 @@ static void exynos4x12_set_frequency(unsigned int old_index, /* 1. Change just s value in apll m,p,s value */ tmp = __raw_readl(EXYNOS4_APLL_CON0); tmp &= ~(0x7 << 0); - tmp |= (exynos4x12_apll_pms_table[new_index] & 0x7); + 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); @@ -416,27 +215,10 @@ static void exynos4x12_set_frequency(unsigned int old_index, } } -static void __init set_volt_table(void) -{ - unsigned int i; - - max_support_idx = L1; - - /* Not supported */ - exynos4x12_freq_table[L0].frequency = CPUFREQ_ENTRY_INVALID; - - for (i = 0 ; i < CPUFREQ_LEVEL_END ; i++) - exynos4x12_volt_table[i] = asv_voltage_4x12[i]; -} - int exynos4x12_cpufreq_init(struct exynos_dvfs_info *info) { - int i; - unsigned int tmp; unsigned long rate; - set_volt_table(); - cpu_clk = clk_get(NULL, "armclk"); if (IS_ERR(cpu_clk)) return PTR_ERR(cpu_clk); @@ -455,66 +237,14 @@ int exynos4x12_cpufreq_init(struct exynos_dvfs_info *info) if (IS_ERR(mout_apll)) goto err_mout_apll; - for (i = L0; i < CPUFREQ_LEVEL_END; i++) { - - exynos4x12_clkdiv_table[i].index = i; - - tmp = __raw_readl(EXYNOS4_CLKDIV_CPU); - - tmp &= ~(EXYNOS4_CLKDIV_CPU0_CORE_MASK | - EXYNOS4_CLKDIV_CPU0_COREM0_MASK | - EXYNOS4_CLKDIV_CPU0_COREM1_MASK | - EXYNOS4_CLKDIV_CPU0_PERIPH_MASK | - EXYNOS4_CLKDIV_CPU0_ATB_MASK | - EXYNOS4_CLKDIV_CPU0_PCLKDBG_MASK | - EXYNOS4_CLKDIV_CPU0_APLL_MASK); - - if (soc_is_exynos4212()) { - tmp |= ((clkdiv_cpu0_4212[i][0] << EXYNOS4_CLKDIV_CPU0_CORE_SHIFT) | - (clkdiv_cpu0_4212[i][1] << EXYNOS4_CLKDIV_CPU0_COREM0_SHIFT) | - (clkdiv_cpu0_4212[i][2] << EXYNOS4_CLKDIV_CPU0_COREM1_SHIFT) | - (clkdiv_cpu0_4212[i][3] << EXYNOS4_CLKDIV_CPU0_PERIPH_SHIFT) | - (clkdiv_cpu0_4212[i][4] << EXYNOS4_CLKDIV_CPU0_ATB_SHIFT) | - (clkdiv_cpu0_4212[i][5] << EXYNOS4_CLKDIV_CPU0_PCLKDBG_SHIFT) | - (clkdiv_cpu0_4212[i][6] << EXYNOS4_CLKDIV_CPU0_APLL_SHIFT)); - } else { - tmp &= ~EXYNOS4_CLKDIV_CPU0_CORE2_MASK; - - tmp |= ((clkdiv_cpu0_4412[i][0] << EXYNOS4_CLKDIV_CPU0_CORE_SHIFT) | - (clkdiv_cpu0_4412[i][1] << EXYNOS4_CLKDIV_CPU0_COREM0_SHIFT) | - (clkdiv_cpu0_4412[i][2] << EXYNOS4_CLKDIV_CPU0_COREM1_SHIFT) | - (clkdiv_cpu0_4412[i][3] << EXYNOS4_CLKDIV_CPU0_PERIPH_SHIFT) | - (clkdiv_cpu0_4412[i][4] << EXYNOS4_CLKDIV_CPU0_ATB_SHIFT) | - (clkdiv_cpu0_4412[i][5] << EXYNOS4_CLKDIV_CPU0_PCLKDBG_SHIFT) | - (clkdiv_cpu0_4412[i][6] << EXYNOS4_CLKDIV_CPU0_APLL_SHIFT) | - (clkdiv_cpu0_4412[i][7] << EXYNOS4_CLKDIV_CPU0_CORE2_SHIFT)); - } - - exynos4x12_clkdiv_table[i].clkdiv = tmp; - - tmp = __raw_readl(EXYNOS4_CLKDIV_CPU1); - - if (soc_is_exynos4212()) { - tmp &= ~(EXYNOS4_CLKDIV_CPU1_COPY_MASK | - EXYNOS4_CLKDIV_CPU1_HPM_MASK); - tmp |= ((clkdiv_cpu1_4212[i][0] << EXYNOS4_CLKDIV_CPU1_COPY_SHIFT) | - (clkdiv_cpu1_4212[i][1] << EXYNOS4_CLKDIV_CPU1_HPM_SHIFT)); - } else { - tmp &= ~(EXYNOS4_CLKDIV_CPU1_COPY_MASK | - EXYNOS4_CLKDIV_CPU1_HPM_MASK | - EXYNOS4_CLKDIV_CPU1_CORES_MASK); - tmp |= ((clkdiv_cpu1_4412[i][0] << EXYNOS4_CLKDIV_CPU1_COPY_SHIFT) | - (clkdiv_cpu1_4412[i][1] << EXYNOS4_CLKDIV_CPU1_HPM_SHIFT) | - (clkdiv_cpu1_4412[i][2] << EXYNOS4_CLKDIV_CPU1_CORES_SHIFT)); - } - exynos4x12_clkdiv_table[i].clkdiv1 = tmp; - } + if (soc_is_exynos4212()) + apll_freq_4x12 = apll_freq_4212; + else + apll_freq_4x12 = apll_freq_4412; info->mpll_freq_khz = rate; - info->pm_lock_idx = L5; + /* 800Mhz */ info->pll_safe_idx = L7; - info->max_support_idx = max_support_idx; - info->min_support_idx = min_support_idx; info->cpu_clk = cpu_clk; info->volt_table = exynos4x12_volt_table; info->freq_table = exynos4x12_freq_table; diff --git a/drivers/cpufreq/exynos5250-cpufreq.c b/drivers/cpufreq/exynos5250-cpufreq.c index e64c253cb1698d456ba853bb8c2ce4f03b2016cd..b9344869f822a5bf4845337a60bc5d60afb7412d 100644 --- a/drivers/cpufreq/exynos5250-cpufreq.c +++ b/drivers/cpufreq/exynos5250-cpufreq.c @@ -21,23 +21,18 @@ #include #include -#define CPUFREQ_LEVEL_END (L15 + 1) - -static int max_support_idx; -static int min_support_idx = (CPUFREQ_LEVEL_END - 1); static struct clk *cpu_clk; static struct clk *moutcore; static struct clk *mout_mpll; static struct clk *mout_apll; -struct cpufreq_clkdiv { - unsigned int index; - unsigned int clkdiv; - unsigned int clkdiv1; +static unsigned int exynos5250_volt_table[] = { + 1300000, 1250000, 1225000, 1200000, 1150000, + 1125000, 1100000, 1075000, 1050000, 1025000, + 1012500, 1000000, 975000, 950000, 937500, + 925000 }; -static unsigned int exynos5250_volt_table[CPUFREQ_LEVEL_END]; - static struct cpufreq_frequency_table exynos5250_freq_table[] = { {L0, 1700 * 1000}, {L1, 1600 * 1000}, @@ -47,8 +42,8 @@ static struct cpufreq_frequency_table exynos5250_freq_table[] = { {L5, 1200 * 1000}, {L6, 1100 * 1000}, {L7, 1000 * 1000}, - {L8, 900 * 1000}, - {L9, 800 * 1000}, + {L8, 900 * 1000}, + {L9, 800 * 1000}, {L10, 700 * 1000}, {L11, 600 * 1000}, {L12, 500 * 1000}, @@ -58,78 +53,30 @@ static struct cpufreq_frequency_table exynos5250_freq_table[] = { {0, CPUFREQ_TABLE_END}, }; -static struct cpufreq_clkdiv exynos5250_clkdiv_table[CPUFREQ_LEVEL_END]; - -static unsigned int clkdiv_cpu0_5250[CPUFREQ_LEVEL_END][8] = { +static struct apll_freq apll_freq_5250[] = { /* - * Clock divider value for following - * { ARM, CPUD, ACP, PERIPH, ATB, PCLK_DBG, APLL, ARM2 } - */ - { 0, 3, 7, 7, 7, 3, 5, 0 }, /* 1700 MHz */ - { 0, 3, 7, 7, 7, 1, 4, 0 }, /* 1600 MHz */ - { 0, 2, 7, 7, 7, 1, 4, 0 }, /* 1500 MHz */ - { 0, 2, 7, 7, 6, 1, 4, 0 }, /* 1400 MHz */ - { 0, 2, 7, 7, 6, 1, 3, 0 }, /* 1300 MHz */ - { 0, 2, 7, 7, 5, 1, 3, 0 }, /* 1200 MHz */ - { 0, 3, 7, 7, 5, 1, 3, 0 }, /* 1100 MHz */ - { 0, 1, 7, 7, 4, 1, 2, 0 }, /* 1000 MHz */ - { 0, 1, 7, 7, 4, 1, 2, 0 }, /* 900 MHz */ - { 0, 1, 7, 7, 4, 1, 2, 0 }, /* 800 MHz */ - { 0, 1, 7, 7, 3, 1, 1, 0 }, /* 700 MHz */ - { 0, 1, 7, 7, 3, 1, 1, 0 }, /* 600 MHz */ - { 0, 1, 7, 7, 2, 1, 1, 0 }, /* 500 MHz */ - { 0, 1, 7, 7, 2, 1, 1, 0 }, /* 400 MHz */ - { 0, 1, 7, 7, 1, 1, 1, 0 }, /* 300 MHz */ - { 0, 1, 7, 7, 1, 1, 1, 0 }, /* 200 MHz */ -}; - -static unsigned int clkdiv_cpu1_5250[CPUFREQ_LEVEL_END][2] = { - /* Clock divider value for following - * { COPY, HPM } + * values: + * freq + * clock divider for ARM, CPUD, ACP, PERIPH, ATB, PCLK_DBG, APLL, ARM2 + * clock divider for COPY, HPM, RESERVED + * PLL M, P, S */ - { 0, 2 }, /* 1700 MHz */ - { 0, 2 }, /* 1600 MHz */ - { 0, 2 }, /* 1500 MHz */ - { 0, 2 }, /* 1400 MHz */ - { 0, 2 }, /* 1300 MHz */ - { 0, 2 }, /* 1200 MHz */ - { 0, 2 }, /* 1100 MHz */ - { 0, 2 }, /* 1000 MHz */ - { 0, 2 }, /* 900 MHz */ - { 0, 2 }, /* 800 MHz */ - { 0, 2 }, /* 700 MHz */ - { 0, 2 }, /* 600 MHz */ - { 0, 2 }, /* 500 MHz */ - { 0, 2 }, /* 400 MHz */ - { 0, 2 }, /* 300 MHz */ - { 0, 2 }, /* 200 MHz */ -}; - -static unsigned int exynos5_apll_pms_table[CPUFREQ_LEVEL_END] = { - ((425 << 16) | (6 << 8) | 0), /* 1700 MHz */ - ((200 << 16) | (3 << 8) | 0), /* 1600 MHz */ - ((250 << 16) | (4 << 8) | 0), /* 1500 MHz */ - ((175 << 16) | (3 << 8) | 0), /* 1400 MHz */ - ((325 << 16) | (6 << 8) | 0), /* 1300 MHz */ - ((200 << 16) | (4 << 8) | 0), /* 1200 MHz */ - ((275 << 16) | (6 << 8) | 0), /* 1100 MHz */ - ((125 << 16) | (3 << 8) | 0), /* 1000 MHz */ - ((150 << 16) | (4 << 8) | 0), /* 900 MHz */ - ((100 << 16) | (3 << 8) | 0), /* 800 MHz */ - ((175 << 16) | (3 << 8) | 1), /* 700 MHz */ - ((200 << 16) | (4 << 8) | 1), /* 600 MHz */ - ((125 << 16) | (3 << 8) | 1), /* 500 MHz */ - ((100 << 16) | (3 << 8) | 1), /* 400 MHz */ - ((200 << 16) | (4 << 8) | 2), /* 300 MHz */ - ((100 << 16) | (3 << 8) | 2), /* 200 MHz */ -}; - -/* ASV group voltage table */ -static const unsigned int asv_voltage_5250[CPUFREQ_LEVEL_END] = { - 1300000, 1250000, 1225000, 1200000, 1150000, - 1125000, 1100000, 1075000, 1050000, 1025000, - 1012500, 1000000, 975000, 950000, 937500, - 925000 + APLL_FREQ(1700, 0, 3, 7, 7, 7, 3, 5, 0, 0, 2, 0, 425, 6, 0), + APLL_FREQ(1600, 0, 3, 7, 7, 7, 1, 4, 0, 0, 2, 0, 200, 3, 0), + APLL_FREQ(1500, 0, 2, 7, 7, 7, 1, 4, 0, 0, 2, 0, 250, 4, 0), + APLL_FREQ(1400, 0, 2, 7, 7, 6, 1, 4, 0, 0, 2, 0, 175, 3, 0), + APLL_FREQ(1300, 0, 2, 7, 7, 6, 1, 3, 0, 0, 2, 0, 325, 6, 0), + APLL_FREQ(1200, 0, 2, 7, 7, 5, 1, 3, 0, 0, 2, 0, 200, 4, 0), + APLL_FREQ(1100, 0, 3, 7, 7, 5, 1, 3, 0, 0, 2, 0, 275, 6, 0), + APLL_FREQ(1000, 0, 1, 7, 7, 4, 1, 2, 0, 0, 2, 0, 125, 3, 0), + APLL_FREQ(900, 0, 1, 7, 7, 4, 1, 2, 0, 0, 2, 0, 150, 4, 0), + APLL_FREQ(800, 0, 1, 7, 7, 4, 1, 2, 0, 0, 2, 0, 100, 3, 0), + APLL_FREQ(700, 0, 1, 7, 7, 3, 1, 1, 0, 0, 2, 0, 175, 3, 1), + APLL_FREQ(600, 0, 1, 7, 7, 3, 1, 1, 0, 0, 2, 0, 200, 4, 1), + APLL_FREQ(500, 0, 1, 7, 7, 2, 1, 1, 0, 0, 2, 0, 125, 3, 1), + APLL_FREQ(400, 0, 1, 7, 7, 2, 1, 1, 0, 0, 2, 0, 100, 3, 1), + APLL_FREQ(300, 0, 1, 7, 7, 1, 1, 1, 0, 0, 2, 0, 200, 4, 2), + APLL_FREQ(200, 0, 1, 7, 7, 1, 1, 1, 0, 0, 2, 0, 100, 3, 2), }; static void set_clkdiv(unsigned int div_index) @@ -138,7 +85,7 @@ static void set_clkdiv(unsigned int div_index) /* Change Divider - CPU0 */ - tmp = exynos5250_clkdiv_table[div_index].clkdiv; + tmp = apll_freq_5250[div_index].clk_div_cpu0; __raw_writel(tmp, EXYNOS5_CLKDIV_CPU0); @@ -146,7 +93,7 @@ static void set_clkdiv(unsigned int div_index) cpu_relax(); /* Change Divider - CPU1 */ - tmp = exynos5250_clkdiv_table[div_index].clkdiv1; + tmp = apll_freq_5250[div_index].clk_div_cpu1; __raw_writel(tmp, EXYNOS5_CLKDIV_CPU1); @@ -169,14 +116,14 @@ static void set_apll(unsigned int new_index, } while (tmp != 0x2); /* 2. Set APLL Lock time */ - pdiv = ((exynos5_apll_pms_table[new_index] >> 8) & 0x3f); + pdiv = ((apll_freq_5250[new_index].mps >> 8) & 0x3f); __raw_writel((pdiv * 250), EXYNOS5_APLL_LOCK); /* 3. Change PLL PMS values */ tmp = __raw_readl(EXYNOS5_APLL_CON0); tmp &= ~((0x3ff << 16) | (0x3f << 8) | (0x7 << 0)); - tmp |= exynos5_apll_pms_table[new_index]; + tmp |= apll_freq_5250[new_index].mps; __raw_writel(tmp, EXYNOS5_APLL_CON0); /* 4. wait_lock_time */ @@ -196,10 +143,10 @@ static void set_apll(unsigned int new_index, } -bool exynos5250_pms_change(unsigned int old_index, unsigned int new_index) +static bool exynos5250_pms_change(unsigned int old_index, unsigned int new_index) { - unsigned int old_pm = (exynos5_apll_pms_table[old_index] >> 8); - unsigned int new_pm = (exynos5_apll_pms_table[new_index] >> 8); + unsigned int old_pm = apll_freq_5250[old_index].mps >> 8; + unsigned int new_pm = apll_freq_5250[new_index].mps >> 8; return (old_pm == new_pm) ? 0 : 1; } @@ -216,7 +163,7 @@ static void exynos5250_set_frequency(unsigned int old_index, /* 2. Change just s value in apll m,p,s value */ tmp = __raw_readl(EXYNOS5_APLL_CON0); tmp &= ~(0x7 << 0); - tmp |= (exynos5_apll_pms_table[new_index] & 0x7); + tmp |= apll_freq_5250[new_index].mps & 0x7; __raw_writel(tmp, EXYNOS5_APLL_CON0); } else { @@ -231,7 +178,7 @@ static void exynos5250_set_frequency(unsigned int old_index, /* 1. Change just s value in apll m,p,s value */ tmp = __raw_readl(EXYNOS5_APLL_CON0); tmp &= ~(0x7 << 0); - tmp |= (exynos5_apll_pms_table[new_index] & 0x7); + tmp |= apll_freq_5250[new_index].mps & 0x7; __raw_writel(tmp, EXYNOS5_APLL_CON0); /* 2. Change the system clock divider values */ set_clkdiv(new_index); @@ -245,24 +192,10 @@ static void exynos5250_set_frequency(unsigned int old_index, } } -static void __init set_volt_table(void) -{ - unsigned int i; - - max_support_idx = L0; - - for (i = 0 ; i < CPUFREQ_LEVEL_END ; i++) - exynos5250_volt_table[i] = asv_voltage_5250[i]; -} - int exynos5250_cpufreq_init(struct exynos_dvfs_info *info) { - int i; - unsigned int tmp; unsigned long rate; - set_volt_table(); - cpu_clk = clk_get(NULL, "armclk"); if (IS_ERR(cpu_clk)) return PTR_ERR(cpu_clk); @@ -281,44 +214,9 @@ int exynos5250_cpufreq_init(struct exynos_dvfs_info *info) if (IS_ERR(mout_apll)) goto err_mout_apll; - for (i = L0; i < CPUFREQ_LEVEL_END; i++) { - - exynos5250_clkdiv_table[i].index = i; - - tmp = __raw_readl(EXYNOS5_CLKDIV_CPU0); - - tmp &= ~((0x7 << 0) | (0x7 << 4) | (0x7 << 8) | - (0x7 << 12) | (0x7 << 16) | (0x7 << 20) | - (0x7 << 24) | (0x7 << 28)); - - tmp |= ((clkdiv_cpu0_5250[i][0] << 0) | - (clkdiv_cpu0_5250[i][1] << 4) | - (clkdiv_cpu0_5250[i][2] << 8) | - (clkdiv_cpu0_5250[i][3] << 12) | - (clkdiv_cpu0_5250[i][4] << 16) | - (clkdiv_cpu0_5250[i][5] << 20) | - (clkdiv_cpu0_5250[i][6] << 24) | - (clkdiv_cpu0_5250[i][7] << 28)); - - exynos5250_clkdiv_table[i].clkdiv = tmp; - - tmp = __raw_readl(EXYNOS5_CLKDIV_CPU1); - - tmp &= ~((0x7 << 0) | (0x7 << 4)); - - tmp |= ((clkdiv_cpu1_5250[i][0] << 0) | - (clkdiv_cpu1_5250[i][1] << 4)); - - exynos5250_clkdiv_table[i].clkdiv1 = tmp; - } - info->mpll_freq_khz = rate; - /* 1000Mhz */ - info->pm_lock_idx = L7; /* 800Mhz */ info->pll_safe_idx = L9; - info->max_support_idx = max_support_idx; - info->min_support_idx = min_support_idx; info->cpu_clk = cpu_clk; info->volt_table = exynos5250_volt_table; info->freq_table = exynos5250_freq_table; diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c index 49cda256efb2149c2311e588d9cdb151f87dc103..d7a79662e24c44bdb4c31c18530217b85255a019 100644 --- a/drivers/cpufreq/freq_table.c +++ b/drivers/cpufreq/freq_table.c @@ -63,9 +63,6 @@ int cpufreq_frequency_table_verify(struct cpufreq_policy *policy, pr_debug("request for verification of policy (%u - %u kHz) for cpu %u\n", policy->min, policy->max, policy->cpu); - if (!cpu_online(policy->cpu)) - return -EINVAL; - cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, policy->cpuinfo.max_freq); @@ -121,9 +118,6 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy, break; } - if (!cpu_online(policy->cpu)) - return -EINVAL; - for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) { unsigned int freq = table[i].frequency; if (freq == CPUFREQ_ENTRY_INVALID) @@ -227,6 +221,15 @@ void cpufreq_frequency_table_put_attr(unsigned int cpu) } EXPORT_SYMBOL_GPL(cpufreq_frequency_table_put_attr); +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", + policy->cpu, policy->last_cpu); + per_cpu(cpufreq_show_table, policy->cpu) = per_cpu(cpufreq_show_table, + policy->last_cpu); + per_cpu(cpufreq_show_table, policy->last_cpu) = NULL; +} + struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu) { return per_cpu(cpufreq_show_table, cpu); diff --git a/drivers/cpufreq/highbank-cpufreq.c b/drivers/cpufreq/highbank-cpufreq.c new file mode 100644 index 0000000000000000000000000000000000000000..66e3a71b81a32f5c71242aca6bdfe4961b16587b --- /dev/null +++ b/drivers/cpufreq/highbank-cpufreq.c @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2012 Calxeda, Inc. + * + * 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. + * + * This driver provides the clk notifier callbacks that are used when + * the cpufreq-cpu0 driver changes to frequency to alert the highbank + * EnergyCore Management Engine (ECME) about the need to change + * voltage. The ECME interfaces with the actual voltage regulators. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include + +#define HB_CPUFREQ_CHANGE_NOTE 0x80000001 +#define HB_CPUFREQ_IPC_LEN 7 +#define HB_CPUFREQ_VOLT_RETRIES 15 + +static int hb_voltage_change(unsigned int freq) +{ + int i; + u32 msg[HB_CPUFREQ_IPC_LEN]; + + msg[0] = HB_CPUFREQ_CHANGE_NOTE; + msg[1] = freq / 1000000; + for (i = 2; i < HB_CPUFREQ_IPC_LEN; i++) + msg[i] = 0; + + return pl320_ipc_transmit(msg); +} + +static int hb_cpufreq_clk_notify(struct notifier_block *nb, + unsigned long action, void *hclk) +{ + struct clk_notifier_data *clk_data = hclk; + int i = 0; + + if (action == PRE_RATE_CHANGE) { + if (clk_data->new_rate > clk_data->old_rate) + while (hb_voltage_change(clk_data->new_rate)) + if (i++ > HB_CPUFREQ_VOLT_RETRIES) + return NOTIFY_BAD; + } else if (action == POST_RATE_CHANGE) { + if (clk_data->new_rate < clk_data->old_rate) + while (hb_voltage_change(clk_data->new_rate)) + if (i++ > HB_CPUFREQ_VOLT_RETRIES) + return NOTIFY_BAD; + } + + return NOTIFY_DONE; +} + +static struct notifier_block hb_cpufreq_clk_nb = { + .notifier_call = hb_cpufreq_clk_notify, +}; + +static int hb_cpufreq_driver_init(void) +{ + struct platform_device_info devinfo = { .name = "cpufreq-cpu0", }; + struct device *cpu_dev; + struct clk *cpu_clk; + struct device_node *np; + int ret; + + if (!of_machine_is_compatible("calxeda,highbank")) + return -ENODEV; + + for_each_child_of_node(of_find_node_by_path("/cpus"), np) + if (of_get_property(np, "operating-points", NULL)) + break; + + if (!np) { + pr_err("failed to find highbank cpufreq node\n"); + return -ENOENT; + } + + cpu_dev = get_cpu_device(0); + if (!cpu_dev) { + pr_err("failed to get highbank cpufreq device\n"); + ret = -ENODEV; + goto out_put_node; + } + + cpu_dev->of_node = np; + + cpu_clk = clk_get(cpu_dev, NULL); + if (IS_ERR(cpu_clk)) { + ret = PTR_ERR(cpu_clk); + pr_err("failed to get cpu0 clock: %d\n", ret); + goto out_put_node; + } + + ret = clk_notifier_register(cpu_clk, &hb_cpufreq_clk_nb); + if (ret) { + pr_err("failed to register clk notifier: %d\n", ret); + goto out_put_node; + } + + /* Instantiate cpufreq-cpu0 */ + platform_device_register_full(&devinfo); + +out_put_node: + of_node_put(np); + return ret; +} +module_init(hb_cpufreq_driver_init); + +MODULE_AUTHOR("Mark Langsdorf "); +MODULE_DESCRIPTION("Calxeda Highbank cpufreq driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c new file mode 100644 index 0000000000000000000000000000000000000000..d6b6ef350cb621f49323b4e8ff4c61b41a9cc69d --- /dev/null +++ b/drivers/cpufreq/imx6q-cpufreq.c @@ -0,0 +1,336 @@ +/* + * Copyright (C) 2013 Freescale Semiconductor, Inc. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PU_SOC_VOLTAGE_NORMAL 1250000 +#define PU_SOC_VOLTAGE_HIGH 1275000 +#define FREQ_1P2_GHZ 1200000000 + +static struct regulator *arm_reg; +static struct regulator *pu_reg; +static struct regulator *soc_reg; + +static struct clk *arm_clk; +static struct clk *pll1_sys_clk; +static struct clk *pll1_sw_clk; +static struct clk *step_clk; +static struct clk *pll2_pfd2_396m_clk; + +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; +} + +static int imx6q_set_target(struct cpufreq_policy *policy, + unsigned int target_freq, unsigned int relation) +{ + struct cpufreq_freqs freqs; + struct opp *opp; + unsigned long freq_hz, volt, volt_old; + unsigned int index, cpu; + int ret; + + ret = cpufreq_frequency_table_target(policy, freq_table, target_freq, + relation, &index); + if (ret) { + dev_err(cpu_dev, "failed to match target frequency %d: %d\n", + target_freq, ret); + return ret; + } + + freqs.new = freq_table[index].frequency; + freq_hz = freqs.new * 1000; + freqs.old = clk_get_rate(arm_clk) / 1000; + + if (freqs.old == freqs.new) + return 0; + + for_each_online_cpu(cpu) { + freqs.cpu = cpu; + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + } + + rcu_read_lock(); + opp = 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); + rcu_read_unlock(); + volt_old = regulator_get_voltage(arm_reg); + + dev_dbg(cpu_dev, "%u MHz, %ld mV --> %u MHz, %ld mV\n", + freqs.old / 1000, volt_old / 1000, + freqs.new / 1000, volt / 1000); + + /* scaling up? scale voltage before frequency */ + if (freqs.new > freqs.old) { + ret = regulator_set_voltage_tol(arm_reg, volt, 0); + if (ret) { + dev_err(cpu_dev, + "failed to scale vddarm up: %d\n", ret); + return ret; + } + + /* + * Need to increase vddpu and vddsoc for safety + * if we are about to run at 1.2 GHz. + */ + if (freqs.new == FREQ_1P2_GHZ / 1000) { + regulator_set_voltage_tol(pu_reg, + PU_SOC_VOLTAGE_HIGH, 0); + regulator_set_voltage_tol(soc_reg, + PU_SOC_VOLTAGE_HIGH, 0); + } + } + + /* + * The setpoints are selected per PLL/PDF frequencies, so we need to + * reprogram PLL for frequency scaling. The procedure of reprogramming + * PLL1 is as below. + * + * - Enable pll2_pfd2_396m_clk and reparent pll1_sw_clk to it + * - Reprogram pll1_sys_clk and reparent pll1_sw_clk back to it + * - Disable pll2_pfd2_396m_clk + */ + clk_prepare_enable(pll2_pfd2_396m_clk); + clk_set_parent(step_clk, pll2_pfd2_396m_clk); + clk_set_parent(pll1_sw_clk, step_clk); + if (freq_hz > clk_get_rate(pll2_pfd2_396m_clk)) { + clk_set_rate(pll1_sys_clk, freqs.new * 1000); + /* + * If we are leaving 396 MHz set-point, we need to enable + * pll1_sys_clk and disable pll2_pfd2_396m_clk to keep + * their use count correct. + */ + if (freqs.old * 1000 <= clk_get_rate(pll2_pfd2_396m_clk)) { + clk_prepare_enable(pll1_sys_clk); + clk_disable_unprepare(pll2_pfd2_396m_clk); + } + clk_set_parent(pll1_sw_clk, pll1_sys_clk); + clk_disable_unprepare(pll2_pfd2_396m_clk); + } else { + /* + * Disable pll1_sys_clk if pll2_pfd2_396m_clk is sufficient + * to provide the frequency. + */ + clk_disable_unprepare(pll1_sys_clk); + } + + /* Ensure the arm clock divider is what we expect */ + ret = clk_set_rate(arm_clk, freqs.new * 1000); + if (ret) { + dev_err(cpu_dev, "failed to set clock rate: %d\n", ret); + regulator_set_voltage_tol(arm_reg, volt_old, 0); + return ret; + } + + /* scaling down? scale voltage after frequency */ + if (freqs.new < freqs.old) { + ret = regulator_set_voltage_tol(arm_reg, volt, 0); + if (ret) + dev_warn(cpu_dev, + "failed to scale vddarm down: %d\n", ret); + + if (freqs.old == FREQ_1P2_GHZ / 1000) { + regulator_set_voltage_tol(pu_reg, + PU_SOC_VOLTAGE_NORMAL, 0); + regulator_set_voltage_tol(soc_reg, + PU_SOC_VOLTAGE_NORMAL, 0); + } + } + + for_each_online_cpu(cpu) { + freqs.cpu = cpu; + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + } + + return 0; +} + +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; +} + +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, + .target = imx6q_set_target, + .get = imx6q_get_speed, + .init = imx6q_cpufreq_init, + .exit = imx6q_cpufreq_exit, + .name = "imx6q-cpufreq", + .attr = imx6q_cpufreq_attr, +}; + +static int imx6q_cpufreq_probe(struct platform_device *pdev) +{ + struct device_node *np; + struct opp *opp; + unsigned long min_volt, max_volt; + int num, ret; + + cpu_dev = &pdev->dev; + + np = of_find_node_by_path("/cpus/cpu@0"); + if (!np) { + dev_err(cpu_dev, "failed to find cpu0 node\n"); + return -ENOENT; + } + + cpu_dev->of_node = np; + + arm_clk = devm_clk_get(cpu_dev, "arm"); + pll1_sys_clk = devm_clk_get(cpu_dev, "pll1_sys"); + pll1_sw_clk = devm_clk_get(cpu_dev, "pll1_sw"); + step_clk = devm_clk_get(cpu_dev, "step"); + pll2_pfd2_396m_clk = devm_clk_get(cpu_dev, "pll2_pfd2_396m"); + if (IS_ERR(arm_clk) || IS_ERR(pll1_sys_clk) || IS_ERR(pll1_sw_clk) || + IS_ERR(step_clk) || IS_ERR(pll2_pfd2_396m_clk)) { + dev_err(cpu_dev, "failed to get clocks\n"); + ret = -ENOENT; + goto put_node; + } + + arm_reg = devm_regulator_get(cpu_dev, "arm"); + pu_reg = devm_regulator_get(cpu_dev, "pu"); + soc_reg = devm_regulator_get(cpu_dev, "soc"); + if (!arm_reg || !pu_reg || !soc_reg) { + dev_err(cpu_dev, "failed to get regulators\n"); + ret = -ENOENT; + goto put_node; + } + + /* We expect an OPP table supplied by platform */ + num = 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); + if (ret) { + dev_err(cpu_dev, "failed to init cpufreq table: %d\n", ret); + goto put_node; + } + + if (of_property_read_u32(np, "clock-latency", &transition_latency)) + transition_latency = CPUFREQ_ETERNAL; + + /* + * OPP is maintained in order of increasing frequency, and + * freq_table initialised from OPP is therefore sorted in the + * same order. + */ + rcu_read_lock(); + opp = 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, + freq_table[--num].frequency * 1000, true); + max_volt = opp_get_voltage(opp); + rcu_read_unlock(); + ret = regulator_set_voltage_time(arm_reg, min_volt, max_volt); + if (ret > 0) + transition_latency += ret * 1000; + + /* Count vddpu and vddsoc latency in for 1.2 GHz support */ + if (freq_table[num].frequency == FREQ_1P2_GHZ / 1000) { + ret = regulator_set_voltage_time(pu_reg, PU_SOC_VOLTAGE_NORMAL, + PU_SOC_VOLTAGE_HIGH); + if (ret > 0) + transition_latency += ret * 1000; + ret = regulator_set_voltage_time(soc_reg, PU_SOC_VOLTAGE_NORMAL, + PU_SOC_VOLTAGE_HIGH); + if (ret > 0) + transition_latency += ret * 1000; + } + + ret = cpufreq_register_driver(&imx6q_cpufreq_driver); + if (ret) { + dev_err(cpu_dev, "failed register driver: %d\n", ret); + goto free_freq_table; + } + + of_node_put(np); + return 0; + +free_freq_table: + opp_free_cpufreq_table(cpu_dev, &freq_table); +put_node: + of_node_put(np); + return ret; +} + +static int imx6q_cpufreq_remove(struct platform_device *pdev) +{ + cpufreq_unregister_driver(&imx6q_cpufreq_driver); + opp_free_cpufreq_table(cpu_dev, &freq_table); + + return 0; +} + +static struct platform_driver imx6q_cpufreq_platdrv = { + .driver = { + .name = "imx6q-cpufreq", + .owner = THIS_MODULE, + }, + .probe = imx6q_cpufreq_probe, + .remove = imx6q_cpufreq_remove, +}; +module_platform_driver(imx6q_cpufreq_platdrv); + +MODULE_AUTHOR("Shawn Guo "); +MODULE_DESCRIPTION("Freescale i.MX6Q cpufreq driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c new file mode 100644 index 0000000000000000000000000000000000000000..096fde0ebcb5b9e2fb2d411f62e12b0702a319d0 --- /dev/null +++ b/drivers/cpufreq/intel_pstate.c @@ -0,0 +1,823 @@ +/* + * cpufreq_snb.c: Native P state management for Intel processors + * + * (C) Copyright 2012 Intel Corporation + * Author: Dirk Brandewie + * + * 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; version 2 + * of the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define SAMPLE_COUNT 3 + +#define FRAC_BITS 8 +#define int_tofp(X) ((int64_t)(X) << FRAC_BITS) +#define fp_toint(X) ((X) >> FRAC_BITS) + +static inline int32_t mul_fp(int32_t x, int32_t y) +{ + return ((int64_t)x * (int64_t)y) >> FRAC_BITS; +} + +static inline int32_t div_fp(int32_t x, int32_t y) +{ + return div_s64((int64_t)x << FRAC_BITS, (int64_t)y); +} + +struct sample { + ktime_t start_time; + ktime_t end_time; + int core_pct_busy; + int pstate_pct_busy; + u64 duration_us; + u64 idletime_us; + u64 aperf; + u64 mperf; + int freq; +}; + +struct pstate_data { + int current_pstate; + int min_pstate; + int max_pstate; + int turbo_pstate; +}; + +struct _pid { + int setpoint; + int32_t integral; + int32_t p_gain; + int32_t i_gain; + int32_t d_gain; + int deadband; + int last_err; +}; + +struct cpudata { + int cpu; + + char name[64]; + + struct timer_list timer; + + struct pstate_adjust_policy *pstate_policy; + struct pstate_data pstate; + struct _pid pid; + struct _pid idle_pid; + + int min_pstate_count; + int idle_mode; + + ktime_t prev_sample; + u64 prev_idle_time_us; + u64 prev_aperf; + u64 prev_mperf; + int sample_ptr; + struct sample samples[SAMPLE_COUNT]; +}; + +static struct cpudata **all_cpu_data; +struct pstate_adjust_policy { + int sample_rate_ms; + int deadband; + int setpoint; + int p_gain_pct; + int d_gain_pct; + int i_gain_pct; +}; + +static struct pstate_adjust_policy default_policy = { + .sample_rate_ms = 10, + .deadband = 0, + .setpoint = 109, + .p_gain_pct = 17, + .d_gain_pct = 0, + .i_gain_pct = 4, +}; + +struct perf_limits { + int no_turbo; + int max_perf_pct; + int min_perf_pct; + int32_t max_perf; + int32_t min_perf; +}; + +static struct perf_limits limits = { + .no_turbo = 0, + .max_perf_pct = 100, + .max_perf = int_tofp(1), + .min_perf_pct = 0, + .min_perf = 0, +}; + +static inline void pid_reset(struct _pid *pid, int setpoint, int busy, + int deadband, int integral) { + pid->setpoint = setpoint; + pid->deadband = deadband; + pid->integral = int_tofp(integral); + pid->last_err = setpoint - busy; +} + +static inline void pid_p_gain_set(struct _pid *pid, int percent) +{ + pid->p_gain = div_fp(int_tofp(percent), int_tofp(100)); +} + +static inline void pid_i_gain_set(struct _pid *pid, int percent) +{ + pid->i_gain = div_fp(int_tofp(percent), int_tofp(100)); +} + +static inline void pid_d_gain_set(struct _pid *pid, int percent) +{ + + pid->d_gain = div_fp(int_tofp(percent), int_tofp(100)); +} + +static signed int pid_calc(struct _pid *pid, int busy) +{ + signed int err, result; + int32_t pterm, dterm, fp_error; + int32_t integral_limit; + + err = pid->setpoint - busy; + fp_error = int_tofp(err); + + if (abs(err) <= pid->deadband) + return 0; + + pterm = mul_fp(pid->p_gain, fp_error); + + pid->integral += fp_error; + + /* limit the integral term */ + integral_limit = int_tofp(30); + if (pid->integral > integral_limit) + pid->integral = integral_limit; + if (pid->integral < -integral_limit) + pid->integral = -integral_limit; + + dterm = mul_fp(pid->d_gain, (err - pid->last_err)); + pid->last_err = err; + + result = pterm + mul_fp(pid->integral, pid->i_gain) + dterm; + + return (signed int)fp_toint(result); +} + +static inline void intel_pstate_busy_pid_reset(struct cpudata *cpu) +{ + pid_p_gain_set(&cpu->pid, cpu->pstate_policy->p_gain_pct); + pid_d_gain_set(&cpu->pid, cpu->pstate_policy->d_gain_pct); + pid_i_gain_set(&cpu->pid, cpu->pstate_policy->i_gain_pct); + + pid_reset(&cpu->pid, + cpu->pstate_policy->setpoint, + 100, + cpu->pstate_policy->deadband, + 0); +} + +static inline void intel_pstate_idle_pid_reset(struct cpudata *cpu) +{ + pid_p_gain_set(&cpu->idle_pid, cpu->pstate_policy->p_gain_pct); + pid_d_gain_set(&cpu->idle_pid, cpu->pstate_policy->d_gain_pct); + pid_i_gain_set(&cpu->idle_pid, cpu->pstate_policy->i_gain_pct); + + pid_reset(&cpu->idle_pid, + 75, + 50, + cpu->pstate_policy->deadband, + 0); +} + +static inline void intel_pstate_reset_all_pid(void) +{ + unsigned int cpu; + for_each_online_cpu(cpu) { + if (all_cpu_data[cpu]) + intel_pstate_busy_pid_reset(all_cpu_data[cpu]); + } +} + +/************************** debugfs begin ************************/ +static int pid_param_set(void *data, u64 val) +{ + *(u32 *)data = val; + intel_pstate_reset_all_pid(); + return 0; +} +static int pid_param_get(void *data, u64 *val) +{ + *val = *(u32 *)data; + return 0; +} +DEFINE_SIMPLE_ATTRIBUTE(fops_pid_param, pid_param_get, + pid_param_set, "%llu\n"); + +struct pid_param { + char *name; + void *value; +}; + +static struct pid_param pid_files[] = { + {"sample_rate_ms", &default_policy.sample_rate_ms}, + {"d_gain_pct", &default_policy.d_gain_pct}, + {"i_gain_pct", &default_policy.i_gain_pct}, + {"deadband", &default_policy.deadband}, + {"setpoint", &default_policy.setpoint}, + {"p_gain_pct", &default_policy.p_gain_pct}, + {NULL, NULL} +}; + +static struct dentry *debugfs_parent; +static void intel_pstate_debug_expose_params(void) +{ + int i = 0; + + debugfs_parent = debugfs_create_dir("pstate_snb", NULL); + if (IS_ERR_OR_NULL(debugfs_parent)) + return; + while (pid_files[i].name) { + debugfs_create_file(pid_files[i].name, 0660, + debugfs_parent, pid_files[i].value, + &fops_pid_param); + i++; + } +} + +/************************** debugfs end ************************/ + +/************************** sysfs begin ************************/ +#define show_one(file_name, object) \ + static ssize_t show_##file_name \ + (struct kobject *kobj, struct attribute *attr, char *buf) \ + { \ + return sprintf(buf, "%u\n", limits.object); \ + } + +static ssize_t store_no_turbo(struct kobject *a, struct attribute *b, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; + limits.no_turbo = clamp_t(int, input, 0 , 1); + + return count; +} + +static ssize_t store_max_perf_pct(struct kobject *a, struct attribute *b, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; + + limits.max_perf_pct = clamp_t(int, input, 0 , 100); + limits.max_perf = div_fp(int_tofp(limits.max_perf_pct), int_tofp(100)); + return count; +} + +static ssize_t store_min_perf_pct(struct kobject *a, struct attribute *b, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; + limits.min_perf_pct = clamp_t(int, input, 0 , 100); + limits.min_perf = div_fp(int_tofp(limits.min_perf_pct), int_tofp(100)); + + return count; +} + +show_one(no_turbo, no_turbo); +show_one(max_perf_pct, max_perf_pct); +show_one(min_perf_pct, min_perf_pct); + +define_one_global_rw(no_turbo); +define_one_global_rw(max_perf_pct); +define_one_global_rw(min_perf_pct); + +static struct attribute *intel_pstate_attributes[] = { + &no_turbo.attr, + &max_perf_pct.attr, + &min_perf_pct.attr, + NULL +}; + +static struct attribute_group intel_pstate_attr_group = { + .attrs = intel_pstate_attributes, +}; +static struct kobject *intel_pstate_kobject; + +static void intel_pstate_sysfs_expose_params(void) +{ + int rc; + + intel_pstate_kobject = kobject_create_and_add("intel_pstate", + &cpu_subsys.dev_root->kobj); + BUG_ON(!intel_pstate_kobject); + rc = sysfs_create_group(intel_pstate_kobject, + &intel_pstate_attr_group); + BUG_ON(rc); +} + +/************************** sysfs end ************************/ + +static int intel_pstate_min_pstate(void) +{ + u64 value; + rdmsrl(0xCE, value); + return (value >> 40) & 0xFF; +} + +static int intel_pstate_max_pstate(void) +{ + u64 value; + rdmsrl(0xCE, value); + return (value >> 8) & 0xFF; +} + +static int intel_pstate_turbo_pstate(void) +{ + u64 value; + int nont, ret; + rdmsrl(0x1AD, value); + nont = intel_pstate_max_pstate(); + ret = ((value) & 255); + if (ret <= nont) + ret = nont; + return ret; +} + +static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max) +{ + int max_perf = cpu->pstate.turbo_pstate; + int min_perf; + if (limits.no_turbo) + max_perf = cpu->pstate.max_pstate; + + max_perf = fp_toint(mul_fp(int_tofp(max_perf), limits.max_perf)); + *max = clamp_t(int, max_perf, + cpu->pstate.min_pstate, cpu->pstate.turbo_pstate); + + min_perf = fp_toint(mul_fp(int_tofp(max_perf), limits.min_perf)); + *min = clamp_t(int, min_perf, + cpu->pstate.min_pstate, max_perf); +} + +static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate) +{ + int max_perf, min_perf; + + intel_pstate_get_min_max(cpu, &min_perf, &max_perf); + + pstate = clamp_t(int, pstate, min_perf, max_perf); + + if (pstate == cpu->pstate.current_pstate) + return; + +#ifndef MODULE + trace_cpu_frequency(pstate * 100000, cpu->cpu); +#endif + cpu->pstate.current_pstate = pstate; + wrmsrl(MSR_IA32_PERF_CTL, pstate << 8); + +} + +static inline void intel_pstate_pstate_increase(struct cpudata *cpu, int steps) +{ + int target; + target = cpu->pstate.current_pstate + steps; + + intel_pstate_set_pstate(cpu, target); +} + +static inline void intel_pstate_pstate_decrease(struct cpudata *cpu, int steps) +{ + int target; + target = cpu->pstate.current_pstate - steps; + intel_pstate_set_pstate(cpu, target); +} + +static void intel_pstate_get_cpu_pstates(struct cpudata *cpu) +{ + sprintf(cpu->name, "Intel 2nd generation core"); + + cpu->pstate.min_pstate = intel_pstate_min_pstate(); + cpu->pstate.max_pstate = intel_pstate_max_pstate(); + cpu->pstate.turbo_pstate = intel_pstate_turbo_pstate(); + + /* + * goto max pstate so we don't slow up boot if we are built-in if we are + * a module we will take care of it during normal operation + */ + intel_pstate_set_pstate(cpu, cpu->pstate.max_pstate); +} + +static inline void intel_pstate_calc_busy(struct cpudata *cpu, + struct sample *sample) +{ + u64 core_pct; + sample->pstate_pct_busy = 100 - div64_u64( + sample->idletime_us * 100, + sample->duration_us); + core_pct = div64_u64(sample->aperf * 100, sample->mperf); + sample->freq = cpu->pstate.turbo_pstate * core_pct * 1000; + + sample->core_pct_busy = div_s64((sample->pstate_pct_busy * core_pct), + 100); +} + +static inline void intel_pstate_sample(struct cpudata *cpu) +{ + ktime_t now; + u64 idle_time_us; + u64 aperf, mperf; + + now = ktime_get(); + idle_time_us = get_cpu_idle_time_us(cpu->cpu, NULL); + + rdmsrl(MSR_IA32_APERF, aperf); + rdmsrl(MSR_IA32_MPERF, mperf); + /* for the first sample, don't actually record a sample, just + * set the baseline */ + if (cpu->prev_idle_time_us > 0) { + cpu->sample_ptr = (cpu->sample_ptr + 1) % SAMPLE_COUNT; + cpu->samples[cpu->sample_ptr].start_time = cpu->prev_sample; + cpu->samples[cpu->sample_ptr].end_time = now; + cpu->samples[cpu->sample_ptr].duration_us = + ktime_us_delta(now, cpu->prev_sample); + cpu->samples[cpu->sample_ptr].idletime_us = + idle_time_us - cpu->prev_idle_time_us; + + cpu->samples[cpu->sample_ptr].aperf = aperf; + cpu->samples[cpu->sample_ptr].mperf = mperf; + cpu->samples[cpu->sample_ptr].aperf -= cpu->prev_aperf; + cpu->samples[cpu->sample_ptr].mperf -= cpu->prev_mperf; + + intel_pstate_calc_busy(cpu, &cpu->samples[cpu->sample_ptr]); + } + + cpu->prev_sample = now; + cpu->prev_idle_time_us = idle_time_us; + cpu->prev_aperf = aperf; + cpu->prev_mperf = mperf; +} + +static inline void intel_pstate_set_sample_time(struct cpudata *cpu) +{ + int sample_time, delay; + + sample_time = cpu->pstate_policy->sample_rate_ms; + delay = msecs_to_jiffies(sample_time); + delay -= jiffies % delay; + mod_timer_pinned(&cpu->timer, jiffies + delay); +} + +static inline void intel_pstate_idle_mode(struct cpudata *cpu) +{ + cpu->idle_mode = 1; +} + +static inline void intel_pstate_normal_mode(struct cpudata *cpu) +{ + cpu->idle_mode = 0; +} + +static inline int intel_pstate_get_scaled_busy(struct cpudata *cpu) +{ + int32_t busy_scaled; + int32_t core_busy, turbo_pstate, current_pstate; + + core_busy = int_tofp(cpu->samples[cpu->sample_ptr].core_pct_busy); + turbo_pstate = int_tofp(cpu->pstate.turbo_pstate); + current_pstate = int_tofp(cpu->pstate.current_pstate); + busy_scaled = mul_fp(core_busy, div_fp(turbo_pstate, current_pstate)); + + return fp_toint(busy_scaled); +} + +static inline void intel_pstate_adjust_busy_pstate(struct cpudata *cpu) +{ + int busy_scaled; + struct _pid *pid; + signed int ctl = 0; + int steps; + + pid = &cpu->pid; + busy_scaled = intel_pstate_get_scaled_busy(cpu); + + ctl = pid_calc(pid, busy_scaled); + + steps = abs(ctl); + if (ctl < 0) + intel_pstate_pstate_increase(cpu, steps); + else + intel_pstate_pstate_decrease(cpu, steps); +} + +static inline void intel_pstate_adjust_idle_pstate(struct cpudata *cpu) +{ + int busy_scaled; + struct _pid *pid; + int ctl = 0; + int steps; + + pid = &cpu->idle_pid; + + busy_scaled = intel_pstate_get_scaled_busy(cpu); + + ctl = pid_calc(pid, 100 - busy_scaled); + + steps = abs(ctl); + if (ctl < 0) + intel_pstate_pstate_decrease(cpu, steps); + else + intel_pstate_pstate_increase(cpu, steps); + + if (cpu->pstate.current_pstate == cpu->pstate.min_pstate) + intel_pstate_normal_mode(cpu); +} + +static void intel_pstate_timer_func(unsigned long __data) +{ + struct cpudata *cpu = (struct cpudata *) __data; + + intel_pstate_sample(cpu); + + if (!cpu->idle_mode) + intel_pstate_adjust_busy_pstate(cpu); + else + intel_pstate_adjust_idle_pstate(cpu); + +#if defined(XPERF_FIX) + if (cpu->pstate.current_pstate == cpu->pstate.min_pstate) { + cpu->min_pstate_count++; + if (!(cpu->min_pstate_count % 5)) { + intel_pstate_set_pstate(cpu, cpu->pstate.max_pstate); + intel_pstate_idle_mode(cpu); + } + } else + cpu->min_pstate_count = 0; +#endif + intel_pstate_set_sample_time(cpu); +} + +#define ICPU(model, policy) \ + { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (unsigned long)&policy } + +static const struct x86_cpu_id intel_pstate_cpu_ids[] = { + ICPU(0x2a, default_policy), + ICPU(0x2d, default_policy), + {} +}; +MODULE_DEVICE_TABLE(x86cpu, intel_pstate_cpu_ids); + +static int intel_pstate_init_cpu(unsigned int cpunum) +{ + + const struct x86_cpu_id *id; + struct cpudata *cpu; + + id = x86_match_cpu(intel_pstate_cpu_ids); + if (!id) + return -ENODEV; + + all_cpu_data[cpunum] = kzalloc(sizeof(struct cpudata), GFP_KERNEL); + if (!all_cpu_data[cpunum]) + return -ENOMEM; + + cpu = all_cpu_data[cpunum]; + + intel_pstate_get_cpu_pstates(cpu); + + cpu->cpu = cpunum; + cpu->pstate_policy = + (struct pstate_adjust_policy *)id->driver_data; + init_timer_deferrable(&cpu->timer); + cpu->timer.function = intel_pstate_timer_func; + cpu->timer.data = + (unsigned long)cpu; + cpu->timer.expires = jiffies + HZ/100; + intel_pstate_busy_pid_reset(cpu); + intel_pstate_idle_pid_reset(cpu); + intel_pstate_sample(cpu); + intel_pstate_set_pstate(cpu, cpu->pstate.max_pstate); + + add_timer_on(&cpu->timer, cpunum); + + pr_info("Intel pstate controlling: cpu %d\n", cpunum); + + return 0; +} + +static unsigned int intel_pstate_get(unsigned int cpu_num) +{ + struct sample *sample; + struct cpudata *cpu; + + cpu = all_cpu_data[cpu_num]; + if (!cpu) + return 0; + sample = &cpu->samples[cpu->sample_ptr]; + return sample->freq; +} + +static int intel_pstate_set_policy(struct cpufreq_policy *policy) +{ + struct cpudata *cpu; + int min, max; + + cpu = all_cpu_data[policy->cpu]; + + intel_pstate_get_min_max(cpu, &min, &max); + + limits.min_perf_pct = (policy->min * 100) / policy->cpuinfo.max_freq; + limits.min_perf_pct = clamp_t(int, limits.min_perf_pct, 0 , 100); + limits.min_perf = div_fp(int_tofp(limits.min_perf_pct), int_tofp(100)); + + limits.max_perf_pct = policy->max * 100 / policy->cpuinfo.max_freq; + limits.max_perf_pct = clamp_t(int, limits.max_perf_pct, 0 , 100); + limits.max_perf = div_fp(int_tofp(limits.max_perf_pct), int_tofp(100)); + + if (policy->policy == CPUFREQ_POLICY_PERFORMANCE) { + limits.min_perf_pct = 100; + limits.min_perf = int_tofp(1); + limits.max_perf_pct = 100; + limits.max_perf = int_tofp(1); + limits.no_turbo = 0; + } + + return 0; +} + +static int intel_pstate_verify_policy(struct cpufreq_policy *policy) +{ + cpufreq_verify_within_limits(policy, + policy->cpuinfo.min_freq, + policy->cpuinfo.max_freq); + + if ((policy->policy != CPUFREQ_POLICY_POWERSAVE) && + (policy->policy != CPUFREQ_POLICY_PERFORMANCE)) + return -EINVAL; + + return 0; +} + +static int __cpuinit intel_pstate_cpu_exit(struct cpufreq_policy *policy) +{ + int cpu = policy->cpu; + + del_timer(&all_cpu_data[cpu]->timer); + kfree(all_cpu_data[cpu]); + all_cpu_data[cpu] = NULL; + return 0; +} + +static int __cpuinit intel_pstate_cpu_init(struct cpufreq_policy *policy) +{ + int rc, min_pstate, max_pstate; + struct cpudata *cpu; + + rc = intel_pstate_init_cpu(policy->cpu); + if (rc) + return rc; + + cpu = all_cpu_data[policy->cpu]; + + if (!limits.no_turbo && + limits.min_perf_pct == 100 && limits.max_perf_pct == 100) + policy->policy = CPUFREQ_POLICY_PERFORMANCE; + else + policy->policy = CPUFREQ_POLICY_POWERSAVE; + + intel_pstate_get_min_max(cpu, &min_pstate, &max_pstate); + policy->min = min_pstate * 100000; + policy->max = max_pstate * 100000; + + /* cpuinfo and default policy values */ + policy->cpuinfo.min_freq = cpu->pstate.min_pstate * 100000; + policy->cpuinfo.max_freq = cpu->pstate.turbo_pstate * 100000; + policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; + cpumask_set_cpu(policy->cpu, policy->cpus); + + return 0; +} + +static struct cpufreq_driver intel_pstate_driver = { + .flags = CPUFREQ_CONST_LOOPS, + .verify = intel_pstate_verify_policy, + .setpolicy = intel_pstate_set_policy, + .get = intel_pstate_get, + .init = intel_pstate_cpu_init, + .exit = intel_pstate_cpu_exit, + .name = "intel_pstate", + .owner = THIS_MODULE, +}; + +static void intel_pstate_exit(void) +{ + int cpu; + + sysfs_remove_group(intel_pstate_kobject, + &intel_pstate_attr_group); + debugfs_remove_recursive(debugfs_parent); + + cpufreq_unregister_driver(&intel_pstate_driver); + + if (!all_cpu_data) + return; + + get_online_cpus(); + for_each_online_cpu(cpu) { + if (all_cpu_data[cpu]) { + del_timer_sync(&all_cpu_data[cpu]->timer); + kfree(all_cpu_data[cpu]); + } + } + + put_online_cpus(); + vfree(all_cpu_data); +} +module_exit(intel_pstate_exit); + +static int __initdata no_load; + +static int __init intel_pstate_init(void) +{ + int rc = 0; + const struct x86_cpu_id *id; + + if (no_load) + return -ENODEV; + + id = x86_match_cpu(intel_pstate_cpu_ids); + if (!id) + return -ENODEV; + + pr_info("Intel P-state driver initializing.\n"); + + all_cpu_data = vmalloc(sizeof(void *) * num_possible_cpus()); + if (!all_cpu_data) + return -ENOMEM; + memset(all_cpu_data, 0, sizeof(void *) * num_possible_cpus()); + + rc = cpufreq_register_driver(&intel_pstate_driver); + if (rc) + goto out; + + intel_pstate_debug_expose_params(); + intel_pstate_sysfs_expose_params(); + return rc; +out: + intel_pstate_exit(); + return -ENODEV; +} +device_initcall(intel_pstate_init); + +static int __init intel_pstate_setup(char *str) +{ + if (!str) + return -EINVAL; + + if (!strcmp(str, "disable")) + no_load = 1; + return 0; +} +early_param("intel_pstate", intel_pstate_setup); + +MODULE_AUTHOR("Dirk Brandewie "); +MODULE_DESCRIPTION("'intel_pstate' - P state driver Intel Core processors"); +MODULE_LICENSE("GPL"); diff --git a/drivers/cpufreq/kirkwood-cpufreq.c b/drivers/cpufreq/kirkwood-cpufreq.c new file mode 100644 index 0000000000000000000000000000000000000000..0e83e3c24f5b829b61eb77b880c815b4d6d58c83 --- /dev/null +++ b/drivers/cpufreq/kirkwood-cpufreq.c @@ -0,0 +1,259 @@ +/* + * kirkwood_freq.c: cpufreq driver for the Marvell kirkwood + * + * Copyright (C) 2013 Andrew Lunn + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CPU_SW_INT_BLK BIT(28) + +static struct priv +{ + struct clk *cpu_clk; + struct clk *ddr_clk; + struct clk *powersave_clk; + struct device *dev; + void __iomem *base; +} priv; + +#define STATE_CPU_FREQ 0x01 +#define STATE_DDR_FREQ 0x02 + +/* + * Kirkwood can swap the clock to the CPU between two clocks: + * + * - cpu clk + * - ddr clk + * + * The frequencies are set at runtime before registering this * + * table. + */ +static struct cpufreq_frequency_table kirkwood_freq_table[] = { + {STATE_CPU_FREQ, 0}, /* CPU uses cpuclk */ + {STATE_DDR_FREQ, 0}, /* CPU uses ddrclk */ + {0, CPUFREQ_TABLE_END}, +}; + +static unsigned int kirkwood_cpufreq_get_cpu_frequency(unsigned int cpu) +{ + if (__clk_is_enabled(priv.powersave_clk)) + return kirkwood_freq_table[1].frequency; + return kirkwood_freq_table[0].frequency; +} + +static void kirkwood_cpufreq_set_cpu_state(unsigned int index) +{ + struct cpufreq_freqs freqs; + unsigned int state = kirkwood_freq_table[index].index; + unsigned long reg; + + freqs.old = kirkwood_cpufreq_get_cpu_frequency(0); + freqs.new = kirkwood_freq_table[index].frequency; + freqs.cpu = 0; /* Kirkwood is UP */ + + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + + dev_dbg(priv.dev, "Attempting to set frequency to %i KHz\n", + kirkwood_freq_table[index].frequency); + dev_dbg(priv.dev, "old frequency was %i KHz\n", + kirkwood_cpufreq_get_cpu_frequency(0)); + + if (freqs.old != freqs.new) { + local_irq_disable(); + + /* Disable interrupts to the CPU */ + reg = readl_relaxed(priv.base); + reg |= CPU_SW_INT_BLK; + writel_relaxed(reg, priv.base); + + switch (state) { + case STATE_CPU_FREQ: + clk_disable(priv.powersave_clk); + break; + case STATE_DDR_FREQ: + clk_enable(priv.powersave_clk); + break; + } + + /* Wait-for-Interrupt, while the hardware changes frequency */ + cpu_do_idle(); + + /* Enable interrupts to the CPU */ + reg = readl_relaxed(priv.base); + reg &= ~CPU_SW_INT_BLK; + writel_relaxed(reg, priv.base); + + local_irq_enable(); + } + cpufreq_notify_transition(&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) +{ + unsigned int index = 0; + + if (cpufreq_frequency_table_target(policy, kirkwood_freq_table, + target_freq, relation, &index)) + return -EINVAL; + + kirkwood_cpufreq_set_cpu_state(index); + + return 0; +} + +/* 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; +} + +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, + .target = kirkwood_cpufreq_target, + .init = kirkwood_cpufreq_cpu_init, + .exit = kirkwood_cpufreq_cpu_exit, + .name = "kirkwood-cpufreq", + .owner = THIS_MODULE, + .attr = kirkwood_cpufreq_attr, +}; + +static int kirkwood_cpufreq_probe(struct platform_device *pdev) +{ + struct device_node *np; + struct resource *res; + int err; + + priv.dev = &pdev->dev; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "Cannot get memory resource\n"); + return -ENODEV; + } + priv.base = devm_request_and_ioremap(&pdev->dev, res); + if (!priv.base) { + dev_err(&pdev->dev, "Cannot ioremap\n"); + return -EADDRNOTAVAIL; + } + + np = of_find_node_by_path("/cpus/cpu@0"); + if (!np) + return -ENODEV; + + priv.cpu_clk = of_clk_get_by_name(np, "cpu_clk"); + if (IS_ERR(priv.cpu_clk)) { + dev_err(priv.dev, "Unable to get cpuclk"); + return PTR_ERR(priv.cpu_clk); + } + + clk_prepare_enable(priv.cpu_clk); + kirkwood_freq_table[0].frequency = clk_get_rate(priv.cpu_clk) / 1000; + + priv.ddr_clk = of_clk_get_by_name(np, "ddrclk"); + if (IS_ERR(priv.ddr_clk)) { + dev_err(priv.dev, "Unable to get ddrclk"); + err = PTR_ERR(priv.ddr_clk); + goto out_cpu; + } + + clk_prepare_enable(priv.ddr_clk); + kirkwood_freq_table[1].frequency = clk_get_rate(priv.ddr_clk) / 1000; + + priv.powersave_clk = of_clk_get_by_name(np, "powersave"); + if (IS_ERR(priv.powersave_clk)) { + dev_err(priv.dev, "Unable to get powersave"); + err = PTR_ERR(priv.powersave_clk); + goto out_ddr; + } + clk_prepare(priv.powersave_clk); + + of_node_put(np); + np = NULL; + + err = cpufreq_register_driver(&kirkwood_cpufreq_driver); + if (!err) + return 0; + + dev_err(priv.dev, "Failed to register cpufreq driver"); + + clk_disable_unprepare(priv.powersave_clk); +out_ddr: + clk_disable_unprepare(priv.ddr_clk); +out_cpu: + clk_disable_unprepare(priv.cpu_clk); + of_node_put(np); + + return err; +} + +static int kirkwood_cpufreq_remove(struct platform_device *pdev) +{ + cpufreq_unregister_driver(&kirkwood_cpufreq_driver); + + clk_disable_unprepare(priv.powersave_clk); + clk_disable_unprepare(priv.ddr_clk); + clk_disable_unprepare(priv.cpu_clk); + + return 0; +} + +static struct platform_driver kirkwood_cpufreq_platform_driver = { + .probe = kirkwood_cpufreq_probe, + .remove = kirkwood_cpufreq_remove, + .driver = { + .name = "kirkwood-cpufreq", + .owner = THIS_MODULE, + }, +}; + +module_platform_driver(kirkwood_cpufreq_platform_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Andrew Lunn cpus, cpu_online_mask); + cpumask_setall(policy->cpus); cpufreq_frequency_table_get_attr(maple_cpu_freqs, policy->cpu); return cpufreq_frequency_table_cpuinfo(policy, diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c index 97102b05843fa580435ae0ae5b872d9467b577df..9128c07bafba37c22b46e2b425a43666264fecfe 100644 --- a/drivers/cpufreq/omap-cpufreq.c +++ b/drivers/cpufreq/omap-cpufreq.c @@ -214,10 +214,8 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) * interface to handle this scenario. Additional is_smp() check * is to keep SMP_ON_UP build working. */ - if (is_smp()) { - policy->shared_type = CPUFREQ_SHARED_TYPE_ANY; + if (is_smp()) cpumask_setall(policy->cpus); - } /* FIXME: what's the actual transition time? */ policy->cpuinfo.transition_latency = 300 * 1000; diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c index 056faf6af1a9f75adf7c546632ccb5bacd106bc2..d13a13678b5f1989fd7906d2fb7dd4bcc61e6e06 100644 --- a/drivers/cpufreq/powernow-k8.c +++ b/drivers/cpufreq/powernow-k8.c @@ -1249,39 +1249,59 @@ static struct cpufreq_driver cpufreq_amd64_driver = { .attr = powernow_k8_attr, }; +static void __request_acpi_cpufreq(void) +{ + const char *cur_drv, *drv = "acpi-cpufreq"; + + cur_drv = cpufreq_get_current_driver(); + if (!cur_drv) + goto request; + + if (strncmp(cur_drv, drv, min_t(size_t, strlen(cur_drv), strlen(drv)))) + pr_warn(PFX "WTF driver: %s\n", cur_drv); + + return; + + request: + pr_warn(PFX "This CPU is not supported anymore, using acpi-cpufreq instead.\n"); + request_module(drv); +} + /* driver entry point for init */ static int __cpuinit powernowk8_init(void) { unsigned int i, supported_cpus = 0; - int rv; + int ret; if (static_cpu_has(X86_FEATURE_HW_PSTATE)) { - pr_warn(PFX "this CPU is not supported anymore, using acpi-cpufreq instead.\n"); - request_module("acpi-cpufreq"); + __request_acpi_cpufreq(); return -ENODEV; } if (!x86_match_cpu(powernow_k8_ids)) return -ENODEV; + get_online_cpus(); for_each_online_cpu(i) { - int rc; - smp_call_function_single(i, check_supported_cpu, &rc, 1); - if (rc == 0) + smp_call_function_single(i, check_supported_cpu, &ret, 1); + if (!ret) supported_cpus++; } - if (supported_cpus != num_online_cpus()) + if (supported_cpus != num_online_cpus()) { + put_online_cpus(); return -ENODEV; + } + put_online_cpus(); - rv = cpufreq_register_driver(&cpufreq_amd64_driver); + ret = cpufreq_register_driver(&cpufreq_amd64_driver); + if (ret) + return ret; - if (!rv) - pr_info(PFX "Found %d %s (%d cpu cores) (" VERSION ")\n", - num_online_nodes(), boot_cpu_data.x86_model_id, - supported_cpus); + pr_info(PFX "Found %d %s (%d cpu cores) (" VERSION ")\n", + num_online_nodes(), boot_cpu_data.x86_model_id, supported_cpus); - return rv; + return ret; } /* driver entry point for term */ diff --git a/drivers/cpufreq/spear-cpufreq.c b/drivers/cpufreq/spear-cpufreq.c index 4575cfe41755c1e5b52b2f890a4a1d4c15806612..7e4d77327957f19116275cc3ff605f8897584fa0 100644 --- a/drivers/cpufreq/spear-cpufreq.c +++ b/drivers/cpufreq/spear-cpufreq.c @@ -30,7 +30,7 @@ static struct { u32 cnt; } spear_cpufreq; -int spear_cpufreq_verify(struct cpufreq_policy *policy) +static int spear_cpufreq_verify(struct cpufreq_policy *policy) { return cpufreq_frequency_table_verify(policy, spear_cpufreq.freq_tbl); } @@ -157,7 +157,9 @@ static int spear_cpufreq_target(struct cpufreq_policy *policy, freqs.new = newfreq / 1000; freqs.new /= mult; - cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + + for_each_cpu(freqs.cpu, policy->cpus) + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); if (mult == 2) ret = spear1340_set_cpu_rate(srcclk, newfreq); @@ -170,7 +172,8 @@ static int spear_cpufreq_target(struct cpufreq_policy *policy, freqs.new = clk_get_rate(spear_cpufreq.clk) / 1000; } - cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + for_each_cpu(freqs.cpu, policy->cpus) + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); return ret; } @@ -188,8 +191,7 @@ static int spear_cpufreq_init(struct cpufreq_policy *policy) policy->cpuinfo.transition_latency = spear_cpufreq.transition_latency; policy->cur = spear_cpufreq_get(0); - cpumask_copy(policy->cpus, topology_core_cpumask(policy->cpu)); - cpumask_copy(policy->related_cpus, policy->cpus); + cpumask_setall(policy->cpus); return 0; } diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index e1f6860e069c7350d3fbb5bb499a67bfc581f760..eba69290e0748b8fe5ee201bab4392916675c363 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -144,7 +144,6 @@ int cpuidle_idle_call(void) return 0; } - trace_power_start_rcuidle(POWER_CSTATE, next_state, dev->cpu); trace_cpu_idle_rcuidle(next_state, dev->cpu); if (cpuidle_state_is_coupled(dev, drv, next_state)) @@ -153,7 +152,6 @@ int cpuidle_idle_call(void) else entered_state = cpuidle_enter_state(dev, drv, next_state); - trace_power_end_rcuidle(dev->cpu); trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, dev->cpu); /* give the governor an opportunity to reflect on the outcome */ diff --git a/drivers/hwmon/acpi_power_meter.c b/drivers/hwmon/acpi_power_meter.c index 1672e2a5db46865cd2849927517c528f287c3314..6351aba8819ceec4ff33a2d9c9a8a43ce8114713 100644 --- a/drivers/hwmon/acpi_power_meter.c +++ b/drivers/hwmon/acpi_power_meter.c @@ -911,7 +911,7 @@ static int acpi_power_meter_add(struct acpi_device *device) return res; } -static int acpi_power_meter_remove(struct acpi_device *device, int type) +static int acpi_power_meter_remove(struct acpi_device *device) { struct acpi_power_meter_resource *resource; diff --git a/drivers/hwmon/asus_atk0110.c b/drivers/hwmon/asus_atk0110.c index 56dbcfb3e30170346f16826a37cff51b641e8ef2..b25c64302cbc1911f5d272e50dc05f8477b326c9 100644 --- a/drivers/hwmon/asus_atk0110.c +++ b/drivers/hwmon/asus_atk0110.c @@ -190,7 +190,7 @@ struct atk_acpi_input_buf { }; static int atk_add(struct acpi_device *device); -static int atk_remove(struct acpi_device *device, int type); +static int atk_remove(struct acpi_device *device); static void atk_print_sensor(struct atk_data *data, union acpi_object *obj); static int atk_read_value(struct atk_sensor_data *sensor, u64 *value); static void atk_free_sensors(struct atk_data *data); @@ -1416,7 +1416,7 @@ static int atk_add(struct acpi_device *device) return err; } -static int atk_remove(struct acpi_device *device, int type) +static int atk_remove(struct acpi_device *device) { struct atk_data *data = device->driver_data; dev_dbg(&device->dev, "removing...\n"); diff --git a/drivers/i2c/busses/i2c-scmi.c b/drivers/i2c/busses/i2c-scmi.c index 6aafa3d88ff0438f6585d0a315998bd8bfba5f9f..c447e8d40b78fb5cc3d58b0fb7b48ffff066c28a 100644 --- a/drivers/i2c/busses/i2c-scmi.c +++ b/drivers/i2c/busses/i2c-scmi.c @@ -406,7 +406,7 @@ static int acpi_smbus_cmi_add(struct acpi_device *device) return -EIO; } -static int acpi_smbus_cmi_remove(struct acpi_device *device, int type) +static int acpi_smbus_cmi_remove(struct acpi_device *device) { struct acpi_smbus_cmi *smbus_cmi = acpi_driver_data(device); diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 2df9414a72f7169fe1fccaec285c633ca45f75d1..5d66750138647d619d9521922a3d2c5421db73e4 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -74,7 +74,7 @@ static struct cpuidle_driver intel_idle_driver = { .en_core_tk_irqen = 1, }; /* intel_idle.max_cstate=0 disables driver */ -static int max_cstate = MWAIT_MAX_NUM_CSTATES - 1; +static int max_cstate = CPUIDLE_STATE_MAX - 1; static unsigned int mwait_substates; @@ -90,6 +90,7 @@ struct idle_cpu { * Indicate which enable bits to clear here. */ unsigned long auto_demotion_disable_flags; + bool disable_promotion_to_c1e; }; static const struct idle_cpu *icpu; @@ -108,163 +109,207 @@ static struct cpuidle_state *cpuidle_state_table; */ #define CPUIDLE_FLAG_TLB_FLUSHED 0x10000 +/* + * MWAIT takes an 8-bit "hint" in EAX "suggesting" + * the C-state (top nibble) and sub-state (bottom nibble) + * 0x00 means "MWAIT(C1)", 0x10 means "MWAIT(C2)" etc. + * + * We store the hint at the top of our "flags" for each state. + */ +#define flg2MWAIT(flags) (((flags) >> 24) & 0xFF) +#define MWAIT2flg(eax) ((eax & 0xFF) << 24) + /* * States are indexed by the cstate number, * which is also the index into the MWAIT hint array. * Thus C0 is a dummy. */ -static struct cpuidle_state nehalem_cstates[MWAIT_MAX_NUM_CSTATES] = { - { /* MWAIT C0 */ }, - { /* MWAIT C1 */ +static struct cpuidle_state nehalem_cstates[CPUIDLE_STATE_MAX] = { + { .name = "C1-NHM", .desc = "MWAIT 0x00", - .flags = CPUIDLE_FLAG_TIME_VALID, + .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_TIME_VALID, .exit_latency = 3, .target_residency = 6, .enter = &intel_idle }, - { /* MWAIT C2 */ + { + .name = "C1E-NHM", + .desc = "MWAIT 0x01", + .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_TIME_VALID, + .exit_latency = 10, + .target_residency = 20, + .enter = &intel_idle }, + { .name = "C3-NHM", .desc = "MWAIT 0x10", - .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, + .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, .exit_latency = 20, .target_residency = 80, .enter = &intel_idle }, - { /* MWAIT C3 */ + { .name = "C6-NHM", .desc = "MWAIT 0x20", - .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, + .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, .exit_latency = 200, .target_residency = 800, .enter = &intel_idle }, + { + .enter = NULL } }; -static struct cpuidle_state snb_cstates[MWAIT_MAX_NUM_CSTATES] = { - { /* MWAIT C0 */ }, - { /* MWAIT C1 */ +static struct cpuidle_state snb_cstates[CPUIDLE_STATE_MAX] = { + { .name = "C1-SNB", .desc = "MWAIT 0x00", - .flags = CPUIDLE_FLAG_TIME_VALID, - .exit_latency = 1, - .target_residency = 1, + .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_TIME_VALID, + .exit_latency = 2, + .target_residency = 2, .enter = &intel_idle }, - { /* MWAIT C2 */ + { + .name = "C1E-SNB", + .desc = "MWAIT 0x01", + .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_TIME_VALID, + .exit_latency = 10, + .target_residency = 20, + .enter = &intel_idle }, + { .name = "C3-SNB", .desc = "MWAIT 0x10", - .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, + .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, .exit_latency = 80, .target_residency = 211, .enter = &intel_idle }, - { /* MWAIT C3 */ + { .name = "C6-SNB", .desc = "MWAIT 0x20", - .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, + .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, .exit_latency = 104, .target_residency = 345, .enter = &intel_idle }, - { /* MWAIT C4 */ + { .name = "C7-SNB", .desc = "MWAIT 0x30", - .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, + .flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, .exit_latency = 109, .target_residency = 345, .enter = &intel_idle }, + { + .enter = NULL } }; -static struct cpuidle_state ivb_cstates[MWAIT_MAX_NUM_CSTATES] = { - { /* MWAIT C0 */ }, - { /* MWAIT C1 */ +static struct cpuidle_state ivb_cstates[CPUIDLE_STATE_MAX] = { + { .name = "C1-IVB", .desc = "MWAIT 0x00", - .flags = CPUIDLE_FLAG_TIME_VALID, + .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_TIME_VALID, .exit_latency = 1, .target_residency = 1, .enter = &intel_idle }, - { /* MWAIT C2 */ + { + .name = "C1E-IVB", + .desc = "MWAIT 0x01", + .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_TIME_VALID, + .exit_latency = 10, + .target_residency = 20, + .enter = &intel_idle }, + { .name = "C3-IVB", .desc = "MWAIT 0x10", - .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, + .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, .exit_latency = 59, .target_residency = 156, .enter = &intel_idle }, - { /* MWAIT C3 */ + { .name = "C6-IVB", .desc = "MWAIT 0x20", - .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, + .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, .exit_latency = 80, .target_residency = 300, .enter = &intel_idle }, - { /* MWAIT C4 */ + { .name = "C7-IVB", .desc = "MWAIT 0x30", - .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, + .flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, .exit_latency = 87, .target_residency = 300, .enter = &intel_idle }, + { + .enter = NULL } }; -static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = { - { /* MWAIT C0 */ }, - { /* MWAIT C1 */ - .name = "C1-ATM", +static struct cpuidle_state hsw_cstates[CPUIDLE_STATE_MAX] = { + { + .name = "C1-HSW", .desc = "MWAIT 0x00", - .flags = CPUIDLE_FLAG_TIME_VALID, - .exit_latency = 1, - .target_residency = 4, + .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_TIME_VALID, + .exit_latency = 2, + .target_residency = 2, + .enter = &intel_idle }, + { + .name = "C1E-HSW", + .desc = "MWAIT 0x01", + .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_TIME_VALID, + .exit_latency = 10, + .target_residency = 20, + .enter = &intel_idle }, + { + .name = "C3-HSW", + .desc = "MWAIT 0x10", + .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, + .exit_latency = 33, + .target_residency = 100, + .enter = &intel_idle }, + { + .name = "C6-HSW", + .desc = "MWAIT 0x20", + .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, + .exit_latency = 133, + .target_residency = 400, + .enter = &intel_idle }, + { + .name = "C7s-HSW", + .desc = "MWAIT 0x32", + .flags = MWAIT2flg(0x32) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, + .exit_latency = 166, + .target_residency = 500, + .enter = &intel_idle }, + { + .enter = NULL } +}; + +static struct cpuidle_state atom_cstates[CPUIDLE_STATE_MAX] = { + { + .name = "C1E-ATM", + .desc = "MWAIT 0x00", + .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_TIME_VALID, + .exit_latency = 10, + .target_residency = 20, .enter = &intel_idle }, - { /* MWAIT C2 */ + { .name = "C2-ATM", .desc = "MWAIT 0x10", - .flags = CPUIDLE_FLAG_TIME_VALID, + .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TIME_VALID, .exit_latency = 20, .target_residency = 80, .enter = &intel_idle }, - { /* MWAIT C3 */ }, - { /* MWAIT C4 */ + { .name = "C4-ATM", .desc = "MWAIT 0x30", - .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, + .flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, .exit_latency = 100, .target_residency = 400, .enter = &intel_idle }, - { /* MWAIT C5 */ }, - { /* MWAIT C6 */ + { .name = "C6-ATM", .desc = "MWAIT 0x52", - .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, + .flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, .exit_latency = 140, .target_residency = 560, .enter = &intel_idle }, + { + .enter = NULL } }; -static long get_driver_data(int cstate) -{ - int driver_data; - switch (cstate) { - - case 1: /* MWAIT C1 */ - driver_data = 0x00; - break; - case 2: /* MWAIT C2 */ - driver_data = 0x10; - break; - case 3: /* MWAIT C3 */ - driver_data = 0x20; - break; - case 4: /* MWAIT C4 */ - driver_data = 0x30; - break; - case 5: /* MWAIT C5 */ - driver_data = 0x40; - break; - case 6: /* MWAIT C6 */ - driver_data = 0x52; - break; - default: - driver_data = 0x00; - } - return driver_data; -} - /** * intel_idle * @dev: cpuidle_device @@ -278,8 +323,7 @@ static int intel_idle(struct cpuidle_device *dev, { unsigned long ecx = 1; /* break on interrupt flag */ struct cpuidle_state *state = &drv->states[index]; - struct cpuidle_state_usage *state_usage = &dev->states_usage[index]; - unsigned long eax = (unsigned long)cpuidle_get_statedata(state_usage); + unsigned long eax = flg2MWAIT(state->flags); unsigned int cstate; int cpu = smp_processor_id(); @@ -362,10 +406,19 @@ static void auto_demotion_disable(void *dummy) msr_bits &= ~(icpu->auto_demotion_disable_flags); wrmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits); } +static void c1e_promotion_disable(void *dummy) +{ + unsigned long long msr_bits; + + rdmsrl(MSR_IA32_POWER_CTL, msr_bits); + msr_bits &= ~0x2; + wrmsrl(MSR_IA32_POWER_CTL, msr_bits); +} static const struct idle_cpu idle_cpu_nehalem = { .state_table = nehalem_cstates, .auto_demotion_disable_flags = NHM_C1_AUTO_DEMOTE | NHM_C3_AUTO_DEMOTE, + .disable_promotion_to_c1e = true, }; static const struct idle_cpu idle_cpu_atom = { @@ -379,10 +432,17 @@ static const struct idle_cpu idle_cpu_lincroft = { static const struct idle_cpu idle_cpu_snb = { .state_table = snb_cstates, + .disable_promotion_to_c1e = true, }; static const struct idle_cpu idle_cpu_ivb = { .state_table = ivb_cstates, + .disable_promotion_to_c1e = true, +}; + +static const struct idle_cpu idle_cpu_hsw = { + .state_table = hsw_cstates, + .disable_promotion_to_c1e = true, }; #define ICPU(model, cpu) \ @@ -402,6 +462,9 @@ static const struct x86_cpu_id intel_idle_ids[] = { ICPU(0x2d, idle_cpu_snb), ICPU(0x3a, idle_cpu_ivb), ICPU(0x3e, idle_cpu_ivb), + ICPU(0x3c, idle_cpu_hsw), + ICPU(0x3f, idle_cpu_hsw), + ICPU(0x45, idle_cpu_hsw), {} }; MODULE_DEVICE_TABLE(x86cpu, intel_idle_ids); @@ -484,32 +547,31 @@ static int intel_idle_cpuidle_driver_init(void) drv->state_count = 1; - for (cstate = 1; cstate < MWAIT_MAX_NUM_CSTATES; ++cstate) { - int num_substates; + for (cstate = 0; cstate < CPUIDLE_STATE_MAX; ++cstate) { + int num_substates, mwait_hint, mwait_cstate, mwait_substate; - if (cstate > max_cstate) { + if (cpuidle_state_table[cstate].enter == NULL) + break; + + if (cstate + 1 > max_cstate) { printk(PREFIX "max_cstate %d reached\n", max_cstate); break; } + mwait_hint = flg2MWAIT(cpuidle_state_table[cstate].flags); + mwait_cstate = MWAIT_HINT2CSTATE(mwait_hint); + mwait_substate = MWAIT_HINT2SUBSTATE(mwait_hint); + /* does the state exist in CPUID.MWAIT? */ - num_substates = (mwait_substates >> ((cstate) * 4)) + num_substates = (mwait_substates >> ((mwait_cstate + 1) * 4)) & MWAIT_SUBSTATE_MASK; - if (num_substates == 0) - continue; - /* is the state not enabled? */ - if (cpuidle_state_table[cstate].enter == NULL) { - /* does the driver not know about the state? */ - if (*cpuidle_state_table[cstate].name == '\0') - pr_debug(PREFIX "unaware of model 0x%x" - " MWAIT %d please" - " contact lenb@kernel.org\n", - boot_cpu_data.x86_model, cstate); + + /* if sub-state in table is not enumerated by CPUID */ + if ((mwait_substate + 1) > num_substates) continue; - } - if ((cstate > 2) && + if (((mwait_cstate + 1) > 2) && !boot_cpu_has(X86_FEATURE_NONSTOP_TSC)) mark_tsc_unstable("TSC halts in idle" " states deeper than C2"); @@ -523,6 +585,9 @@ static int intel_idle_cpuidle_driver_init(void) if (icpu->auto_demotion_disable_flags) on_each_cpu(auto_demotion_disable, NULL, 1); + if (icpu->disable_promotion_to_c1e) /* each-cpu is redundant */ + on_each_cpu(c1e_promotion_disable, NULL, 1); + return 0; } @@ -541,25 +606,28 @@ static int intel_idle_cpu_init(int cpu) dev->state_count = 1; - for (cstate = 1; cstate < MWAIT_MAX_NUM_CSTATES; ++cstate) { - int num_substates; + for (cstate = 0; cstate < CPUIDLE_STATE_MAX; ++cstate) { + int num_substates, mwait_hint, mwait_cstate, mwait_substate; + + if (cpuidle_state_table[cstate].enter == NULL) + continue; - if (cstate > max_cstate) { + if (cstate + 1 > max_cstate) { printk(PREFIX "max_cstate %d reached\n", max_cstate); break; } + mwait_hint = flg2MWAIT(cpuidle_state_table[cstate].flags); + mwait_cstate = MWAIT_HINT2CSTATE(mwait_hint); + mwait_substate = MWAIT_HINT2SUBSTATE(mwait_hint); + /* does the state exist in CPUID.MWAIT? */ - num_substates = (mwait_substates >> ((cstate) * 4)) - & MWAIT_SUBSTATE_MASK; - if (num_substates == 0) - continue; - /* is the state not enabled? */ - if (cpuidle_state_table[cstate].enter == NULL) - continue; + num_substates = (mwait_substates >> ((mwait_cstate + 1) * 4)) + & MWAIT_SUBSTATE_MASK; - dev->states_usage[dev->state_count].driver_data = - (void *)get_driver_data(cstate); + /* if sub-state in table is not enumerated by CPUID */ + if ((mwait_substate + 1) > num_substates) + continue; dev->state_count += 1; } diff --git a/drivers/input/misc/atlas_btns.c b/drivers/input/misc/atlas_btns.c index 26f13131639aa8e5432f499efa155403a972607a..5d4402365a5207258dbd9b4b7d68f18489fa1598 100644 --- a/drivers/input/misc/atlas_btns.c +++ b/drivers/input/misc/atlas_btns.c @@ -121,7 +121,7 @@ static int atlas_acpi_button_add(struct acpi_device *device) return err; } -static int atlas_acpi_button_remove(struct acpi_device *device, int type) +static int atlas_acpi_button_remove(struct acpi_device *device) { acpi_status status; diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..9545c9f03809bd88378135dc9c668b8214b1a891 --- /dev/null +++ b/drivers/mailbox/Kconfig @@ -0,0 +1,19 @@ +menuconfig MAILBOX + bool "Mailbox Hardware Support" + help + Mailbox is a framework to control hardware communication between + on-chip processors through queued messages and interrupt driven + signals. Say Y if your platform supports hardware mailboxes. + +if MAILBOX +config PL320_MBOX + bool "ARM PL320 Mailbox" + depends on ARM_AMBA + help + An implementation of the ARM PL320 Interprocessor Communication + Mailbox (IPCM), tailored for the Calxeda Highbank. It is used to + send short messages between Highbank's A9 cores and the EnergyCore + Management Engine, primarily for cpufreq. Say Y here if you want + to use the PL320 IPCM support. + +endif diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..543ad6a795054b1015117f7bea877631b6d18463 --- /dev/null +++ b/drivers/mailbox/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_PL320_MBOX) += pl320-ipc.o diff --git a/drivers/mailbox/pl320-ipc.c b/drivers/mailbox/pl320-ipc.c new file mode 100644 index 0000000000000000000000000000000000000000..c45b3aedafba975f720a1ab422c764ef4fe1b0c4 --- /dev/null +++ b/drivers/mailbox/pl320-ipc.c @@ -0,0 +1,199 @@ +/* + * Copyright 2012 Calxeda, Inc. + * + * 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, see . + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define IPCMxSOURCE(m) ((m) * 0x40) +#define IPCMxDSET(m) (((m) * 0x40) + 0x004) +#define IPCMxDCLEAR(m) (((m) * 0x40) + 0x008) +#define IPCMxDSTATUS(m) (((m) * 0x40) + 0x00C) +#define IPCMxMODE(m) (((m) * 0x40) + 0x010) +#define IPCMxMSET(m) (((m) * 0x40) + 0x014) +#define IPCMxMCLEAR(m) (((m) * 0x40) + 0x018) +#define IPCMxMSTATUS(m) (((m) * 0x40) + 0x01C) +#define IPCMxSEND(m) (((m) * 0x40) + 0x020) +#define IPCMxDR(m, dr) (((m) * 0x40) + ((dr) * 4) + 0x024) + +#define IPCMMIS(irq) (((irq) * 8) + 0x800) +#define IPCMRIS(irq) (((irq) * 8) + 0x804) + +#define MBOX_MASK(n) (1 << (n)) +#define IPC_TX_MBOX 1 +#define IPC_RX_MBOX 2 + +#define CHAN_MASK(n) (1 << (n)) +#define A9_SOURCE 1 +#define M3_SOURCE 0 + +static void __iomem *ipc_base; +static int ipc_irq; +static DEFINE_MUTEX(ipc_m1_lock); +static DECLARE_COMPLETION(ipc_completion); +static ATOMIC_NOTIFIER_HEAD(ipc_notifier); + +static inline void set_destination(int source, int mbox) +{ + __raw_writel(CHAN_MASK(source), ipc_base + IPCMxDSET(mbox)); + __raw_writel(CHAN_MASK(source), ipc_base + IPCMxMSET(mbox)); +} + +static inline void clear_destination(int source, int mbox) +{ + __raw_writel(CHAN_MASK(source), ipc_base + IPCMxDCLEAR(mbox)); + __raw_writel(CHAN_MASK(source), ipc_base + IPCMxMCLEAR(mbox)); +} + +static void __ipc_send(int mbox, u32 *data) +{ + int i; + for (i = 0; i < 7; i++) + __raw_writel(data[i], ipc_base + IPCMxDR(mbox, i)); + __raw_writel(0x1, ipc_base + IPCMxSEND(mbox)); +} + +static u32 __ipc_rcv(int mbox, u32 *data) +{ + int i; + for (i = 0; i < 7; i++) + data[i] = __raw_readl(ipc_base + IPCMxDR(mbox, i)); + return data[1]; +} + +/* blocking implmentation from the A9 side, not usuable in interrupts! */ +int pl320_ipc_transmit(u32 *data) +{ + int ret; + + mutex_lock(&ipc_m1_lock); + + init_completion(&ipc_completion); + __ipc_send(IPC_TX_MBOX, data); + ret = wait_for_completion_timeout(&ipc_completion, + msecs_to_jiffies(1000)); + if (ret == 0) { + ret = -ETIMEDOUT; + goto out; + } + + ret = __ipc_rcv(IPC_TX_MBOX, data); +out: + mutex_unlock(&ipc_m1_lock); + return ret; +} +EXPORT_SYMBOL_GPL(pl320_ipc_transmit); + +static irqreturn_t ipc_handler(int irq, void *dev) +{ + u32 irq_stat; + u32 data[7]; + + irq_stat = __raw_readl(ipc_base + IPCMMIS(1)); + if (irq_stat & MBOX_MASK(IPC_TX_MBOX)) { + __raw_writel(0, ipc_base + IPCMxSEND(IPC_TX_MBOX)); + complete(&ipc_completion); + } + if (irq_stat & MBOX_MASK(IPC_RX_MBOX)) { + __ipc_rcv(IPC_RX_MBOX, data); + atomic_notifier_call_chain(&ipc_notifier, data[0], data + 1); + __raw_writel(2, ipc_base + IPCMxSEND(IPC_RX_MBOX)); + } + + return IRQ_HANDLED; +} + +int pl320_ipc_register_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_register(&ipc_notifier, nb); +} +EXPORT_SYMBOL_GPL(pl320_ipc_register_notifier); + +int pl320_ipc_unregister_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_unregister(&ipc_notifier, nb); +} +EXPORT_SYMBOL_GPL(pl320_ipc_unregister_notifier); + +static int __init pl320_probe(struct amba_device *adev, + const struct amba_id *id) +{ + int ret; + + ipc_base = ioremap(adev->res.start, resource_size(&adev->res)); + if (ipc_base == NULL) + return -ENOMEM; + + __raw_writel(0, ipc_base + IPCMxSEND(IPC_TX_MBOX)); + + ipc_irq = adev->irq[0]; + ret = request_irq(ipc_irq, ipc_handler, 0, dev_name(&adev->dev), NULL); + if (ret < 0) + goto err; + + /* Init slow mailbox */ + __raw_writel(CHAN_MASK(A9_SOURCE), + ipc_base + IPCMxSOURCE(IPC_TX_MBOX)); + __raw_writel(CHAN_MASK(M3_SOURCE), + ipc_base + IPCMxDSET(IPC_TX_MBOX)); + __raw_writel(CHAN_MASK(M3_SOURCE) | CHAN_MASK(A9_SOURCE), + ipc_base + IPCMxMSET(IPC_TX_MBOX)); + + /* Init receive mailbox */ + __raw_writel(CHAN_MASK(M3_SOURCE), + ipc_base + IPCMxSOURCE(IPC_RX_MBOX)); + __raw_writel(CHAN_MASK(A9_SOURCE), + ipc_base + IPCMxDSET(IPC_RX_MBOX)); + __raw_writel(CHAN_MASK(M3_SOURCE) | CHAN_MASK(A9_SOURCE), + ipc_base + IPCMxMSET(IPC_RX_MBOX)); + + return 0; +err: + iounmap(ipc_base); + return ret; +} + +static struct amba_id pl320_ids[] = { + { + .id = 0x00041320, + .mask = 0x000fffff, + }, + { 0, 0 }, +}; + +static struct amba_driver pl320_driver = { + .drv = { + .name = "pl320", + }, + .id_table = pl320_ids, + .probe = pl320_probe, +}; + +static int __init ipc_init(void) +{ + return amba_driver_register(&pl320_driver); +} +module_init(ipc_init); diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 3d6d4fd1e3c5fedfa07bed77f4fb0768b7bfe626..a951c22921d165bb1553de35cb68ffc95ddc3abf 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -734,34 +734,24 @@ static unsigned char acpiphp_max_busnr(struct pci_bus *bus) */ static int acpiphp_bus_add(struct acpiphp_func *func) { - acpi_handle phandle; - struct acpi_device *device, *pdevice; + struct acpi_device *device; int ret_val; - acpi_get_parent(func->handle, &phandle); - if (acpi_bus_get_device(phandle, &pdevice)) { - dbg("no parent device, assuming NULL\n"); - pdevice = NULL; - } if (!acpi_bus_get_device(func->handle, &device)) { dbg("bus exists... trim\n"); /* this shouldn't be in here, so remove * the bus then re-add it... */ - ret_val = acpi_bus_trim(device, 1); - dbg("acpi_bus_trim return %x\n", ret_val); + acpi_bus_trim(device); } - ret_val = acpi_bus_add(&device, pdevice, func->handle, - ACPI_BUS_TYPE_DEVICE); - if (ret_val) { - dbg("error adding bus, %x\n", - -ret_val); - goto acpiphp_bus_add_out; - } - ret_val = acpi_bus_start(device); + ret_val = acpi_bus_scan(func->handle); + if (!ret_val) + ret_val = acpi_bus_get_device(func->handle, &device); + + if (ret_val) + dbg("error adding bus, %x\n", -ret_val); -acpiphp_bus_add_out: return ret_val; } @@ -781,11 +771,8 @@ static int acpiphp_bus_trim(acpi_handle handle) return retval; } - retval = acpi_bus_trim(device, 1); - if (retval) - err("cannot remove from acpi list\n"); - - return retval; + acpi_bus_trim(device); + return 0; } static void acpiphp_set_acpi_region(struct acpiphp_slot *slot) @@ -1130,8 +1117,7 @@ static int acpiphp_configure_bridge (acpi_handle handle) static void handle_bridge_insertion(acpi_handle handle, u32 type) { - struct acpi_device *device, *pdevice; - acpi_handle phandle; + struct acpi_device *device; if ((type != ACPI_NOTIFY_BUS_CHECK) && (type != ACPI_NOTIFY_DEVICE_CHECK)) { @@ -1139,17 +1125,15 @@ static void handle_bridge_insertion(acpi_handle handle, u32 type) return; } - acpi_get_parent(handle, &phandle); - if (acpi_bus_get_device(phandle, &pdevice)) { - dbg("no parent device, assuming NULL\n"); - pdevice = NULL; - } - if (acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE)) { + if (acpi_bus_scan(handle)) { err("cannot add bridge to acpi list\n"); return; } - if (!acpiphp_configure_bridge(handle) && - !acpi_bus_start(device)) + if (acpi_bus_get_device(handle, &device)) { + err("ACPI device object missing\n"); + return; + } + if (!acpiphp_configure_bridge(handle)) add_bridge(handle); else err("cannot configure and start bridge\n"); @@ -1234,6 +1218,8 @@ static void _handle_hotplug_event_bridge(struct work_struct *work) handle = hp_work->handle; type = hp_work->type; + acpi_scan_lock_acquire(); + if (acpi_bus_get_device(handle, &device)) { /* This bridge must have just been physically inserted */ handle_bridge_insertion(handle, type); @@ -1311,6 +1297,7 @@ static void _handle_hotplug_event_bridge(struct work_struct *work) } out: + acpi_scan_lock_release(); kfree(hp_work); /* allocated in handle_hotplug_event_bridge */ } @@ -1357,6 +1344,8 @@ static void _handle_hotplug_event_func(struct work_struct *work) func = (struct acpiphp_func *)context; + acpi_scan_lock_acquire(); + switch (type) { case ACPI_NOTIFY_BUS_CHECK: /* bus re-enumerate */ @@ -1387,6 +1376,7 @@ static void _handle_hotplug_event_func(struct work_struct *work) break; } + acpi_scan_lock_release(); kfree(hp_work); /* allocated in handle_hotplug_event_func */ } diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c index f64ca92253da527ea49b84af968df516f53e43f0..574421bc2fa63bd4e407cafbe2ecd8ca1d22d780 100644 --- a/drivers/pci/hotplug/sgi_hotplug.c +++ b/drivers/pci/hotplug/sgi_hotplug.c @@ -412,7 +412,6 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) if (SN_ACPI_BASE_SUPPORT() && ssdt) { unsigned long long adr; struct acpi_device *pdevice; - struct acpi_device *device; acpi_handle phandle; acpi_handle chandle = NULL; acpi_handle rethandle; @@ -426,6 +425,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) pdevice = NULL; } + acpi_scan_lock_acquire(); /* * Walk the rootbus node's immediate children looking for * the slot's device node(s). There can be more than @@ -448,20 +448,18 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) if (ACPI_SUCCESS(ret) && (adr>>16) == (slot->device_num + 1)) { - ret = acpi_bus_add(&device, pdevice, chandle, - ACPI_BUS_TYPE_DEVICE); + ret = acpi_bus_scan(chandle); if (ACPI_FAILURE(ret)) { - printk(KERN_ERR "%s: acpi_bus_add " + printk(KERN_ERR "%s: acpi_bus_scan " "failed (0x%x) for slot %d " "func %d\n", __func__, ret, (int)(adr>>16), (int)(adr&0xffff)); /* try to continue on */ - } else { - acpi_bus_start(device); } } } + acpi_scan_lock_release(); } /* Call the driver for the new device */ @@ -512,6 +510,7 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot) /* Get the rootbus node pointer */ phandle = PCI_CONTROLLER(slot->pci_bus)->acpi_handle; + acpi_scan_lock_acquire(); /* * Walk the rootbus node's immediate children looking for * the slot's device node(s). There can be more than @@ -539,10 +538,10 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot) ret = acpi_bus_get_device(chandle, &device); if (ACPI_SUCCESS(ret)) - acpi_bus_trim(device, 1); + acpi_bus_trim(device); } } - + acpi_scan_lock_release(); } /* Free the SN resources assigned to the Linux device.*/ diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 1af4008182fd631ed3249cf3341798a650de3922..e407c61559ca0f09c452b9f130a07ac93ad3dba6 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -283,7 +283,6 @@ static struct pci_platform_pm_ops acpi_pci_platform_pm = { .is_manageable = acpi_pci_power_manageable, .set_state = acpi_pci_set_power_state, .choose_state = acpi_pci_choose_state, - .can_wakeup = acpi_pci_can_wakeup, .sleep_wake = acpi_pci_sleep_wake, .run_wake = acpi_pci_run_wake, }; @@ -321,10 +320,65 @@ static int acpi_pci_find_root_bridge(struct device *dev, acpi_handle *handle) return 0; } +static void pci_acpi_setup(struct device *dev) +{ + struct pci_dev *pci_dev = to_pci_dev(dev); + acpi_handle handle = ACPI_HANDLE(dev); + struct acpi_device *adev; + acpi_status status; + acpi_handle dummy; + + /* + * Evaluate and parse _PRT, if exists. This code allows parsing of + * _PRT objects within the scope of non-bridge devices. Note that + * _PRTs within the scope of a PCI bridge assume the bridge's + * subordinate bus number. + * + * TBD: Can _PRTs exist within the scope of non-bridge PCI devices? + */ + status = acpi_get_handle(handle, METHOD_NAME__PRT, &dummy); + if (ACPI_SUCCESS(status)) { + unsigned char bus; + + bus = pci_dev->subordinate ? + pci_dev->subordinate->number : pci_dev->bus->number; + acpi_pci_irq_add_prt(handle, pci_domain_nr(pci_dev->bus), bus); + } + + if (acpi_bus_get_device(handle, &adev) || !adev->wakeup.flags.valid) + return; + + device_set_wakeup_capable(dev, true); + acpi_pci_sleep_wake(pci_dev, false); + + pci_acpi_add_pm_notifier(adev, pci_dev); + if (adev->wakeup.flags.run_wake) + device_set_run_wake(dev, true); +} + +static void pci_acpi_cleanup(struct device *dev) +{ + struct pci_dev *pci_dev = to_pci_dev(dev); + acpi_handle handle = ACPI_HANDLE(dev); + struct acpi_device *adev; + + if (!acpi_bus_get_device(handle, &adev) && adev->wakeup.flags.valid) { + device_set_wakeup_capable(dev, false); + device_set_run_wake(dev, false); + pci_acpi_remove_pm_notifier(adev); + } + + if (pci_dev->subordinate) + acpi_pci_irq_del_prt(pci_domain_nr(pci_dev->bus), + pci_dev->subordinate->number); +} + static struct acpi_bus_type acpi_pci_bus = { .bus = &pci_bus_type, .find_device = acpi_pci_find_device, .find_bridge = acpi_pci_find_root_bridge, + .setup = pci_acpi_setup, + .cleanup = pci_acpi_cleanup, }; static int __init acpi_pci_init(void) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 5cb5820fae40147a29c79913cd1ebadcbfba1348..0c4f641b7be169841e0ec68bc7e7642fc6efaaf4 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -450,7 +450,7 @@ static struct pci_platform_pm_ops *pci_platform_pm; int pci_set_platform_pm(struct pci_platform_pm_ops *ops) { if (!ops->is_manageable || !ops->set_state || !ops->choose_state - || !ops->sleep_wake || !ops->can_wakeup) + || !ops->sleep_wake) return -EINVAL; pci_platform_pm = ops; return 0; @@ -473,11 +473,6 @@ static inline pci_power_t platform_pci_choose_state(struct pci_dev *dev) pci_platform_pm->choose_state(dev) : PCI_POWER_ERROR; } -static inline bool platform_pci_can_wakeup(struct pci_dev *dev) -{ - return pci_platform_pm ? pci_platform_pm->can_wakeup(dev) : false; -} - static inline int platform_pci_sleep_wake(struct pci_dev *dev, bool enable) { return pci_platform_pm ? @@ -1985,25 +1980,6 @@ void pci_pm_init(struct pci_dev *dev) } } -/** - * platform_pci_wakeup_init - init platform wakeup if present - * @dev: PCI device - * - * Some devices don't have PCI PM caps but can still generate wakeup - * events through platform methods (like ACPI events). If @dev supports - * platform wakeup events, set the device flag to indicate as much. This - * may be redundant if the device also supports PCI PM caps, but double - * initialization should be safe in that case. - */ -void platform_pci_wakeup_init(struct pci_dev *dev) -{ - if (!platform_pci_can_wakeup(dev)) - return; - - device_set_wakeup_capable(&dev->dev, true); - platform_pci_sleep_wake(dev, false); -} - static void pci_add_saved_cap(struct pci_dev *pci_dev, struct pci_cap_saved_state *new_cap) { diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index e8518292826f0182bc23206f0b7e25fe88de858f..adfd172c5b9b53ea1797af3d10d7a958f844d777 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -43,9 +43,6 @@ int pci_probe_reset_function(struct pci_dev *dev); * platform; to be used during system-wide transitions from a * sleeping state to the working state and vice versa * - * @can_wakeup: returns 'true' if given device is capable of waking up the - * system from a sleeping state - * * @sleep_wake: enables/disables the system wake up capability of given device * * @run_wake: enables/disables the platform to generate run-time wake-up events @@ -59,7 +56,6 @@ struct pci_platform_pm_ops { bool (*is_manageable)(struct pci_dev *dev); int (*set_state)(struct pci_dev *dev, pci_power_t state); pci_power_t (*choose_state)(struct pci_dev *dev); - bool (*can_wakeup)(struct pci_dev *dev); int (*sleep_wake)(struct pci_dev *dev, bool enable); int (*run_wake)(struct pci_dev *dev, bool enable); }; @@ -74,7 +70,6 @@ extern void pci_wakeup_bus(struct pci_bus *bus); extern void pci_config_pm_runtime_get(struct pci_dev *dev); extern void pci_config_pm_runtime_put(struct pci_dev *dev); extern void pci_pm_init(struct pci_dev *dev); -extern void platform_pci_wakeup_init(struct pci_dev *dev); extern void pci_allocate_cap_save_buffers(struct pci_dev *dev); void pci_free_cap_save_buffers(struct pci_dev *dev); diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 6186f03d84f37c8aa696d3df504e722a5cd36b38..2dcd22d9c816f98c681f572a2f48fbba7da5680b 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -1280,7 +1280,6 @@ static void pci_init_capabilities(struct pci_dev *dev) /* Power Management */ pci_pm_init(dev); - platform_pci_wakeup_init(dev); /* Vital Product Data */ pci_vpd_pci22_init(dev); diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index fcde4e528819c04daf4b919ba00d70a20f7456c3..d9f9a0dbc6f3502333ea4441777afbd3227805ad 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -1910,7 +1910,7 @@ static int asus_acpi_add(struct acpi_device *device) return result; } -static int asus_acpi_remove(struct acpi_device *device, int type) +static int asus_acpi_remove(struct acpi_device *device) { struct asus_laptop *asus = acpi_driver_data(device); diff --git a/drivers/platform/x86/classmate-laptop.c b/drivers/platform/x86/classmate-laptop.c index c87ff16873f9753ef589111763d743bc09ed1409..36e5e6c13db4edbdd0aaae00e405eff248619290 100644 --- a/drivers/platform/x86/classmate-laptop.c +++ b/drivers/platform/x86/classmate-laptop.c @@ -432,7 +432,7 @@ static int cmpc_accel_add_v4(struct acpi_device *acpi) return error; } -static int cmpc_accel_remove_v4(struct acpi_device *acpi, int type) +static int cmpc_accel_remove_v4(struct acpi_device *acpi) { struct input_dev *inputdev; struct cmpc_accel *accel; @@ -668,7 +668,7 @@ static int cmpc_accel_add(struct acpi_device *acpi) return error; } -static int cmpc_accel_remove(struct acpi_device *acpi, int type) +static int cmpc_accel_remove(struct acpi_device *acpi) { struct input_dev *inputdev; struct cmpc_accel *accel; @@ -753,7 +753,7 @@ static int cmpc_tablet_add(struct acpi_device *acpi) cmpc_tablet_idev_init); } -static int cmpc_tablet_remove(struct acpi_device *acpi, int type) +static int cmpc_tablet_remove(struct acpi_device *acpi) { return cmpc_remove_acpi_notify_device(acpi); } @@ -1000,7 +1000,7 @@ static int cmpc_ipml_add(struct acpi_device *acpi) return retval; } -static int cmpc_ipml_remove(struct acpi_device *acpi, int type) +static int cmpc_ipml_remove(struct acpi_device *acpi) { struct ipml200_dev *ipml; @@ -1079,7 +1079,7 @@ static int cmpc_keys_add(struct acpi_device *acpi) cmpc_keys_idev_init); } -static int cmpc_keys_remove(struct acpi_device *acpi, int type) +static int cmpc_keys_remove(struct acpi_device *acpi) { return cmpc_remove_acpi_notify_device(acpi); } diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index a5da0b594f71bcfcc88e17d07335beb3cd318d00..5d26e70bed6c532d51c0fb326bc97f91e1a8a020 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -1501,7 +1501,7 @@ static int eeepc_acpi_add(struct acpi_device *device) return result; } -static int eeepc_acpi_remove(struct acpi_device *device, int type) +static int eeepc_acpi_remove(struct acpi_device *device) { struct eeepc_laptop *eeepc = acpi_driver_data(device); diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c index c4c1a5444b38e3486d0617f0a843e3cc8f9cfd9c..1c9386e7c58ce723ca583714b862604cbcfd25e5 100644 --- a/drivers/platform/x86/fujitsu-laptop.c +++ b/drivers/platform/x86/fujitsu-laptop.c @@ -733,7 +733,7 @@ static int acpi_fujitsu_add(struct acpi_device *device) return result; } -static int acpi_fujitsu_remove(struct acpi_device *device, int type) +static int acpi_fujitsu_remove(struct acpi_device *device) { struct fujitsu_t *fujitsu = acpi_driver_data(device); struct input_dev *input = fujitsu->input; @@ -938,7 +938,7 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device) return result; } -static int acpi_fujitsu_hotkey_remove(struct acpi_device *device, int type) +static int acpi_fujitsu_hotkey_remove(struct acpi_device *device) { struct fujitsu_hotkey_t *fujitsu_hotkey = acpi_driver_data(device); struct input_dev *input = fujitsu_hotkey->input; diff --git a/drivers/platform/x86/fujitsu-tablet.c b/drivers/platform/x86/fujitsu-tablet.c index 174ca01c4aa71fda16dac075bc3171860c70c06e..570926c10014d53ef3c1a2afc4de6aa87eb71a96 100644 --- a/drivers/platform/x86/fujitsu-tablet.c +++ b/drivers/platform/x86/fujitsu-tablet.c @@ -431,7 +431,7 @@ static int acpi_fujitsu_add(struct acpi_device *adev) return 0; } -static int acpi_fujitsu_remove(struct acpi_device *adev, int type) +static int acpi_fujitsu_remove(struct acpi_device *adev) { free_irq(fujitsu.irq, fujitsu_interrupt); release_region(fujitsu.io_base, fujitsu.io_length); diff --git a/drivers/platform/x86/hp_accel.c b/drivers/platform/x86/hp_accel.c index 18d74f29dcb21784c6f83814f46e58d67366ae3c..e64a7a870d42146c910ffb39b955c29a11a88080 100644 --- a/drivers/platform/x86/hp_accel.c +++ b/drivers/platform/x86/hp_accel.c @@ -337,7 +337,7 @@ static int lis3lv02d_add(struct acpi_device *device) return ret; } -static int lis3lv02d_remove(struct acpi_device *device, int type) +static int lis3lv02d_remove(struct acpi_device *device) { if (!device) return -EINVAL; diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index 64bfb30a52e9a022c3a1c08be8f4f59c0a8a5ee6..17f00b8dc5cbcb841540f07c7330775bcb5393df 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c @@ -834,7 +834,7 @@ static int ideapad_acpi_add(struct acpi_device *adevice) return ret; } -static int ideapad_acpi_remove(struct acpi_device *adevice, int type) +static int ideapad_acpi_remove(struct acpi_device *adevice) { struct ideapad_private *priv = dev_get_drvdata(&adevice->dev); int i; diff --git a/drivers/platform/x86/intel_menlow.c b/drivers/platform/x86/intel_menlow.c index 3271ac85115e4914237c902575e0f694ea0dd6f9..d6cfc1558c2f1e067d8fd72edb1dc7ce3ecd00e3 100644 --- a/drivers/platform/x86/intel_menlow.c +++ b/drivers/platform/x86/intel_menlow.c @@ -200,7 +200,7 @@ static int intel_menlow_memory_add(struct acpi_device *device) } -static int intel_menlow_memory_remove(struct acpi_device *device, int type) +static int intel_menlow_memory_remove(struct acpi_device *device) { struct thermal_cooling_device *cdev = acpi_driver_data(device); diff --git a/drivers/platform/x86/panasonic-laptop.c b/drivers/platform/x86/panasonic-laptop.c index 8e8caa767d6aec521e65cd42475e3b2950c32907..4add9a31bf601cf151c5f0b6ce938de73ba0aa96 100644 --- a/drivers/platform/x86/panasonic-laptop.c +++ b/drivers/platform/x86/panasonic-laptop.c @@ -176,7 +176,7 @@ enum SINF_BITS { SINF_NUM_BATTERIES = 0, /* R1 handles SINF_AC_CUR_BRIGHT as SINF_CUR_BRIGHT, doesn't know AC state */ static int acpi_pcc_hotkey_add(struct acpi_device *device); -static int acpi_pcc_hotkey_remove(struct acpi_device *device, int type); +static int acpi_pcc_hotkey_remove(struct acpi_device *device); static void acpi_pcc_hotkey_notify(struct acpi_device *device, u32 event); static const struct acpi_device_id pcc_device_ids[] = { @@ -663,7 +663,7 @@ static int __init acpi_pcc_init(void) return 0; } -static int acpi_pcc_hotkey_remove(struct acpi_device *device, int type) +static int acpi_pcc_hotkey_remove(struct acpi_device *device) { struct pcc_acpi *pcc = acpi_driver_data(device); diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index b8ad71f7863fa2b0fa9c741e9605ffdfe5a92fcf..ceb41eff4230ecc0f21d765b376a42b6fbbe2eac 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -2740,7 +2740,7 @@ static int sony_nc_add(struct acpi_device *device) return result; } -static int sony_nc_remove(struct acpi_device *device, int type) +static int sony_nc_remove(struct acpi_device *device) { struct sony_nc_value *item; @@ -4111,7 +4111,7 @@ static irqreturn_t sony_pic_irq(int irq, void *dev_id) * ACPI driver * *****************/ -static int sony_pic_remove(struct acpi_device *device, int type) +static int sony_pic_remove(struct acpi_device *device) { struct sony_pic_ioport *io, *tmp_io; struct sony_pic_irq *irq, *tmp_irq; diff --git a/drivers/platform/x86/topstar-laptop.c b/drivers/platform/x86/topstar-laptop.c index d727bfee89a6eef656aef88df13b78e4d082ad49..4ab618c63b457e0bbf5a613274ab10a3e76f26cc 100644 --- a/drivers/platform/x86/topstar-laptop.c +++ b/drivers/platform/x86/topstar-laptop.c @@ -157,7 +157,7 @@ static int acpi_topstar_add(struct acpi_device *device) return -ENODEV; } -static int acpi_topstar_remove(struct acpi_device *device, int type) +static int acpi_topstar_remove(struct acpi_device *device) { struct topstar_hkey *tps_hkey = acpi_driver_data(device); diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index c2727895794ca51d7623bc820c6aeadd422fa4c5..904476b2fa8f3e1de0bcc003f440a35c058befd9 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -1118,7 +1118,7 @@ static int toshiba_acpi_setup_backlight(struct toshiba_acpi_dev *dev) return 0; } -static int toshiba_acpi_remove(struct acpi_device *acpi_dev, int type) +static int toshiba_acpi_remove(struct acpi_device *acpi_dev) { struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev); @@ -1250,7 +1250,7 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev) return 0; error: - toshiba_acpi_remove(acpi_dev, 0); + toshiba_acpi_remove(acpi_dev); return ret; } diff --git a/drivers/platform/x86/toshiba_bluetooth.c b/drivers/platform/x86/toshiba_bluetooth.c index e95be0b74859b286c92979a1de1e766abaf4e65e..74dd01ae343b01f5f5a9827c5ec02f11ceee61b5 100644 --- a/drivers/platform/x86/toshiba_bluetooth.c +++ b/drivers/platform/x86/toshiba_bluetooth.c @@ -32,7 +32,7 @@ MODULE_LICENSE("GPL"); static int toshiba_bt_rfkill_add(struct acpi_device *device); -static int toshiba_bt_rfkill_remove(struct acpi_device *device, int type); +static int toshiba_bt_rfkill_remove(struct acpi_device *device); static void toshiba_bt_rfkill_notify(struct acpi_device *device, u32 event); static const struct acpi_device_id bt_device_ids[] = { @@ -122,7 +122,7 @@ static int toshiba_bt_rfkill_add(struct acpi_device *device) return result; } -static int toshiba_bt_rfkill_remove(struct acpi_device *device, int type) +static int toshiba_bt_rfkill_remove(struct acpi_device *device) { /* clean up */ return 0; diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index 42a4dcc25f92ae0cfacc127b6310594bda477e25..e4ac38aca5802ef995ad84fc9d191749075771ff 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -92,7 +92,7 @@ module_param(debug_dump_wdg, bool, 0444); MODULE_PARM_DESC(debug_dump_wdg, "Dump available WMI interfaces [0/1]"); -static int acpi_wmi_remove(struct acpi_device *device, int type); +static int acpi_wmi_remove(struct acpi_device *device); static int acpi_wmi_add(struct acpi_device *device); static void acpi_wmi_notify(struct acpi_device *device, u32 event); @@ -917,7 +917,7 @@ static void acpi_wmi_notify(struct acpi_device *device, u32 event) } } -static int acpi_wmi_remove(struct acpi_device *device, int type) +static int acpi_wmi_remove(struct acpi_device *device) { acpi_remove_address_space_handler(device->handle, ACPI_ADR_SPACE_EC, &acpi_wmi_ec_space_handler); diff --git a/drivers/platform/x86/xo15-ebook.c b/drivers/platform/x86/xo15-ebook.c index 16d340c3b85256fad50fe57c4ca620d49f8fdcc1..4b1377bd59446a50405e00414418adf9ac8f8381 100644 --- a/drivers/platform/x86/xo15-ebook.c +++ b/drivers/platform/x86/xo15-ebook.c @@ -150,7 +150,7 @@ static int ebook_switch_add(struct acpi_device *device) return error; } -static int ebook_switch_remove(struct acpi_device *device, int type) +static int ebook_switch_remove(struct acpi_device *device) { struct ebook_switch *button = acpi_driver_data(device); diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index 72e822e17d475c3ba632fc8e33afbadc55d52d33..8813fc03aa099fbb37b3a2321160fef4cdd51ef0 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c @@ -90,7 +90,7 @@ static int pnpacpi_set_resources(struct pnp_dev *dev) pnp_dbg(&dev->dev, "set resources\n"); handle = DEVICE_ACPI_HANDLE(&dev->dev); - if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &acpi_dev))) { + if (!handle || acpi_bus_get_device(handle, &acpi_dev)) { dev_dbg(&dev->dev, "ACPI device not found in %s!\n", __func__); return -ENODEV; } @@ -123,7 +123,7 @@ static int pnpacpi_disable_resources(struct pnp_dev *dev) dev_dbg(&dev->dev, "disable resources\n"); handle = DEVICE_ACPI_HANDLE(&dev->dev); - if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &acpi_dev))) { + if (!handle || acpi_bus_get_device(handle, &acpi_dev)) { dev_dbg(&dev->dev, "ACPI device not found in %s!\n", __func__); return 0; } @@ -145,7 +145,7 @@ static bool pnpacpi_can_wakeup(struct pnp_dev *dev) acpi_handle handle; handle = DEVICE_ACPI_HANDLE(&dev->dev); - if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &acpi_dev))) { + if (!handle || acpi_bus_get_device(handle, &acpi_dev)) { dev_dbg(&dev->dev, "ACPI device not found in %s!\n", __func__); return false; } @@ -160,7 +160,7 @@ static int pnpacpi_suspend(struct pnp_dev *dev, pm_message_t state) int error = 0; handle = DEVICE_ACPI_HANDLE(&dev->dev); - if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &acpi_dev))) { + if (!handle || acpi_bus_get_device(handle, &acpi_dev)) { dev_dbg(&dev->dev, "ACPI device not found in %s!\n", __func__); return 0; } @@ -197,7 +197,7 @@ static int pnpacpi_resume(struct pnp_dev *dev) acpi_handle handle = DEVICE_ACPI_HANDLE(&dev->dev); int error = 0; - if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &acpi_dev))) { + if (!handle || acpi_bus_get_device(handle, &acpi_dev)) { dev_dbg(&dev->dev, "ACPI device not found in %s!\n", __func__); return -ENODEV; } diff --git a/drivers/pnp/pnpbios/Kconfig b/drivers/pnp/pnpbios/Kconfig index b986d9fa3b9af0d6dfad6ef5c3ef63f45a0359c1..50c3dd065e030d0dd7463dfc3c09523d6cb78fe8 100644 --- a/drivers/pnp/pnpbios/Kconfig +++ b/drivers/pnp/pnpbios/Kconfig @@ -2,8 +2,8 @@ # Plug and Play BIOS configuration # config PNPBIOS - bool "Plug and Play BIOS support (EXPERIMENTAL)" - depends on ISA && X86 && EXPERIMENTAL + bool "Plug and Play BIOS support" + depends on ISA && X86 default n ---help--- Linux uses the PNPBIOS as defined in "Plug and Play BIOS diff --git a/drivers/staging/quickstart/quickstart.c b/drivers/staging/quickstart/quickstart.c index cac320738142f1caeb0479705f920f8d47180e08..adb8da564cf6356a8fcdabe35a17256f8e766f4d 100644 --- a/drivers/staging/quickstart/quickstart.c +++ b/drivers/staging/quickstart/quickstart.c @@ -296,7 +296,7 @@ static int quickstart_acpi_add(struct acpi_device *device) return ret; } -static int quickstart_acpi_remove(struct acpi_device *device, int type) +static int quickstart_acpi_remove(struct acpi_device *device) { acpi_status status; struct quickstart_acpi *quickstart; diff --git a/drivers/video/backlight/apple_bl.c b/drivers/video/backlight/apple_bl.c index f088d4c07381cec00155a4818a14cb8bc1f96357..d843296766896d3abe8e2e2b10c34cbd23aed40a 100644 --- a/drivers/video/backlight/apple_bl.c +++ b/drivers/video/backlight/apple_bl.c @@ -196,7 +196,7 @@ static int apple_bl_add(struct acpi_device *dev) return 0; } -static int apple_bl_remove(struct acpi_device *dev, int type) +static int apple_bl_remove(struct acpi_device *dev) { backlight_device_unregister(apple_backlight_device); diff --git a/drivers/xen/xen-acpi-pad.c b/drivers/xen/xen-acpi-pad.c index da39191e7278aa0aa26a242ca5c4542551e200c2..c763479ed85ebcfc47eaa76014d3bcc765a2f68e 100644 --- a/drivers/xen/xen-acpi-pad.c +++ b/drivers/xen/xen-acpi-pad.c @@ -140,8 +140,7 @@ static int acpi_pad_add(struct acpi_device *device) return 0; } -static int acpi_pad_remove(struct acpi_device *device, - int type) +static int acpi_pad_remove(struct acpi_device *device) { mutex_lock(&xen_cpu_lock); xen_acpi_pad_idle_cpus(0); diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c index 2df555c66d57d463381042632ae124ad53aecb42..aec3d5c98c94fa1d3d79de15a44dfa2a4a77e329 100644 --- a/fs/sysfs/group.c +++ b/fs/sysfs/group.c @@ -205,6 +205,48 @@ void sysfs_unmerge_group(struct kobject *kobj, } EXPORT_SYMBOL_GPL(sysfs_unmerge_group); +/** + * sysfs_add_link_to_group - add a symlink to an attribute group. + * @kobj: The kobject containing the group. + * @group_name: The name of the group. + * @target: The target kobject of the symlink to create. + * @link_name: The name of the symlink to create. + */ +int sysfs_add_link_to_group(struct kobject *kobj, const char *group_name, + struct kobject *target, const char *link_name) +{ + struct sysfs_dirent *dir_sd; + int error = 0; + + dir_sd = sysfs_get_dirent(kobj->sd, NULL, group_name); + if (!dir_sd) + return -ENOENT; + + error = sysfs_create_link_sd(dir_sd, target, link_name); + sysfs_put(dir_sd); + + return error; +} +EXPORT_SYMBOL_GPL(sysfs_add_link_to_group); + +/** + * sysfs_remove_link_from_group - remove a symlink from an attribute group. + * @kobj: The kobject containing the group. + * @group_name: The name of the group. + * @link_name: The name of the symlink to remove. + */ +void sysfs_remove_link_from_group(struct kobject *kobj, const char *group_name, + const char *link_name) +{ + struct sysfs_dirent *dir_sd; + + dir_sd = sysfs_get_dirent(kobj->sd, NULL, group_name); + if (dir_sd) { + sysfs_hash_and_remove(dir_sd, NULL, link_name); + sysfs_put(dir_sd); + } +} +EXPORT_SYMBOL_GPL(sysfs_remove_link_from_group); EXPORT_SYMBOL_GPL(sysfs_create_group); EXPORT_SYMBOL_GPL(sysfs_update_group); diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index 3c9eb5624f5e195d6e2b06908f3b21396ccc8723..8c940df97a52bd3e836ef34fc4654553ea105c8d 100644 --- a/fs/sysfs/symlink.c +++ b/fs/sysfs/symlink.c @@ -21,26 +21,17 @@ #include "sysfs.h" -static int sysfs_do_create_link(struct kobject *kobj, struct kobject *target, - const char *name, int warn) +static int sysfs_do_create_link_sd(struct sysfs_dirent *parent_sd, + struct kobject *target, + const char *name, int warn) { - struct sysfs_dirent *parent_sd = NULL; struct sysfs_dirent *target_sd = NULL; struct sysfs_dirent *sd = NULL; struct sysfs_addrm_cxt acxt; enum kobj_ns_type ns_type; int error; - BUG_ON(!name); - - if (!kobj) - parent_sd = &sysfs_root; - else - parent_sd = kobj->sd; - - error = -EFAULT; - if (!parent_sd) - goto out_put; + BUG_ON(!name || !parent_sd); /* target->sd can go away beneath us but is protected with * sysfs_assoc_lock. Fetch target_sd from it. @@ -95,6 +86,34 @@ static int sysfs_do_create_link(struct kobject *kobj, struct kobject *target, return error; } +/** + * sysfs_create_link_sd - create symlink to a given object. + * @sd: directory we're creating the link in. + * @target: object we're pointing to. + * @name: name of the symlink. + */ +int sysfs_create_link_sd(struct sysfs_dirent *sd, struct kobject *target, + const char *name) +{ + return sysfs_do_create_link_sd(sd, target, name, 1); +} + +static int sysfs_do_create_link(struct kobject *kobj, struct kobject *target, + const char *name, int warn) +{ + struct sysfs_dirent *parent_sd = NULL; + + if (!kobj) + parent_sd = &sysfs_root; + else + parent_sd = kobj->sd; + + if (!parent_sd) + return -EFAULT; + + return sysfs_do_create_link_sd(parent_sd, target, name, warn); +} + /** * sysfs_create_link - create symlink between two objects. * @kobj: object whose directory we're creating the link in. diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index d73c0932bbd6f688b811784236fc1a78ffce3c37..d1e4043eb0c3ab2962bb1b1154b9dc4b20050305 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -240,3 +240,5 @@ void unmap_bin_file(struct sysfs_dirent *attr_sd); * symlink.c */ extern const struct inode_operations sysfs_symlink_inode_operations; +int sysfs_create_link_sd(struct sysfs_dirent *sd, struct kobject *target, + const char *name); diff --git a/include/acpi/acbuffer.h b/include/acpi/acbuffer.h index a1e45cdd729a0ba7c36c0492e1c6cecec186df3a..c927a0b1de78569aa0e49ab8ad13b7b284f2b997 100644 --- a/include/acpi/acbuffer.h +++ b/include/acpi/acbuffer.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h index 0943457e0fa5eba6f78d36a20e24d310dfb91bd6..14ceff788c40b75cc7e7240db5bb07587d6ec783 100644 --- a/include/acpi/acconfig.h +++ b/include/acpi/acconfig.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -138,7 +138,7 @@ /* Maximum sleep allowed via Sleep() operator */ -#define ACPI_MAX_SLEEP 2000 /* Two seconds */ +#define ACPI_MAX_SLEEP 2000 /* 2000 millisec == two seconds */ /* Address Range lists are per-space_id (Memory and I/O only) */ @@ -150,11 +150,6 @@ * *****************************************************************************/ -/* Number of distinct GPE register blocks and register width */ - -#define ACPI_MAX_GPE_BLOCKS 2 -#define ACPI_GPE_REGISTER_WIDTH 8 - /* Method info (in WALK_STATE), containing local variables and argumetns */ #define ACPI_METHOD_NUM_LOCALS 8 @@ -163,12 +158,6 @@ #define ACPI_METHOD_NUM_ARGS 7 #define ACPI_METHOD_MAX_ARG 6 -/* Length of _HID, _UID, _CID, and UUID values */ - -#define ACPI_DEVICE_ID_LENGTH 0x09 -#define ACPI_MAX_CID_LENGTH 48 -#define ACPI_UUID_LENGTH 16 - /* * Operand Stack (in WALK_STATE), Must be large enough to contain METHOD_MAX_ARG */ @@ -186,17 +175,6 @@ */ #define ACPI_RESULTS_OBJ_NUM_MAX 255 -/* Names within the namespace are 4 bytes long */ - -#define ACPI_NAME_SIZE 4 -#define ACPI_PATH_SEGMENT_LENGTH 5 /* 4 chars for name + 1 char for separator */ -#define ACPI_PATH_SEPARATOR '.' - -/* Sizes for ACPI table headers */ - -#define ACPI_OEM_ID_SIZE 6 -#define ACPI_OEM_TABLE_ID_SIZE 8 - /* Constants used in searching for the RSDP in low memory */ #define ACPI_EBDA_PTR_LOCATION 0x0000040E /* Physical Address */ @@ -213,6 +191,7 @@ /* Maximum space_ids for Operation Regions */ #define ACPI_MAX_ADDRESS_SPACE 255 +#define ACPI_NUM_DEFAULT_SPACES 4 /* Array sizes. Used for range checking also */ diff --git a/include/acpi/acexcep.h b/include/acpi/acexcep.h index 6c3890e021400da74d95594efad153b058ded1ed..9bf59d0e8aaae263add7ad0ef5af51ed856e70b7 100644 --- a/include/acpi/acexcep.h +++ b/include/acpi/acexcep.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/acnames.h b/include/acpi/acnames.h index 7665df6632841c5b3da828041405146b5e46859e..ce08ef7d969cffb7516bd65fed39eda6bc29f39b 100644 --- a/include/acpi/acnames.h +++ b/include/acpi/acnames.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/acoutput.h b/include/acpi/acoutput.h index 2457ac8496552d632b8075b6c4284e30008f22ae..9885276178e0a83e0cfc1989e616900a83e71ee7 100644 --- a/include/acpi/acoutput.h +++ b/include/acpi/acoutput.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -72,6 +72,7 @@ #define ACPI_EXAMPLE 0x00004000 #define ACPI_DRIVER 0x00008000 #define DT_COMPILER 0x00010000 +#define ASL_PREPROCESSOR 0x00020000 #define ACPI_ALL_COMPONENTS 0x0001FFFF #define ACPI_COMPONENT_DEFAULT (ACPI_ALL_COMPONENTS) @@ -262,18 +263,140 @@ * Common parameters used for debug output functions: * line number, function name, module(file) name, component ID */ -#define ACPI_DEBUG_PARAMETERS __LINE__, ACPI_GET_FUNCTION_NAME, _acpi_module_name, _COMPONENT +#define ACPI_DEBUG_PARAMETERS \ + __LINE__, ACPI_GET_FUNCTION_NAME, _acpi_module_name, _COMPONENT + +/* Check if debug output is currently dynamically enabled */ + +#define ACPI_IS_DEBUG_ENABLED(level, component) \ + ((level & acpi_dbg_level) && (component & acpi_dbg_layer)) /* * Master debug print macros * Print message if and only if: * 1) Debug print for the current component is enabled * 2) Debug error level or trace level for the print statement is enabled + * + * November 2012: Moved the runtime check for whether to actually emit the + * debug message outside of the print function itself. This improves overall + * performance at a relatively small code cost. Implementation involves the + * use of variadic macros supported by C99. + * + * Note: the ACPI_DO_WHILE0 macro is used to prevent some compilers from + * complaining about these constructs. On other compilers the do...while + * adds some extra code, so this feature is optional. */ -#define ACPI_DEBUG_PRINT(plist) acpi_debug_print plist -#define ACPI_DEBUG_PRINT_RAW(plist) acpi_debug_print_raw plist - +#ifdef ACPI_USE_DO_WHILE_0 +#define ACPI_DO_WHILE0(a) do a while(0) #else +#define ACPI_DO_WHILE0(a) a +#endif + +/* DEBUG_PRINT functions */ + +#define ACPI_DEBUG_PRINT(plist) ACPI_ACTUAL_DEBUG plist +#define ACPI_DEBUG_PRINT_RAW(plist) ACPI_ACTUAL_DEBUG_RAW plist + +/* Helper macros for DEBUG_PRINT */ + +#define ACPI_DO_DEBUG_PRINT(function, level, line, filename, modulename, component, ...) \ + ACPI_DO_WHILE0 ({ \ + if (ACPI_IS_DEBUG_ENABLED (level, component)) \ + { \ + function (level, line, filename, modulename, component, __VA_ARGS__); \ + } \ + }) + +#define ACPI_ACTUAL_DEBUG(level, line, filename, modulename, component, ...) \ + ACPI_DO_DEBUG_PRINT (acpi_debug_print, level, line, \ + filename, modulename, component, __VA_ARGS__) + +#define ACPI_ACTUAL_DEBUG_RAW(level, line, filename, modulename, component, ...) \ + ACPI_DO_DEBUG_PRINT (acpi_debug_print_raw, level, line, \ + filename, modulename, component, __VA_ARGS__) + +/* + * Function entry tracing + * + * The name of the function is emitted as a local variable that is + * intended to be used by both the entry trace and the exit trace. + */ + +/* Helper macro */ + +#define ACPI_TRACE_ENTRY(name, function, cast, param) \ + ACPI_FUNCTION_NAME (name) \ + function (ACPI_DEBUG_PARAMETERS, cast (param)) + +/* The actual entry trace macros */ + +#define ACPI_FUNCTION_TRACE(name) \ + ACPI_FUNCTION_NAME(name) \ + acpi_ut_trace (ACPI_DEBUG_PARAMETERS) + +#define ACPI_FUNCTION_TRACE_PTR(name, pointer) \ + ACPI_TRACE_ENTRY (name, acpi_ut_trace_ptr, (void *), pointer) + +#define ACPI_FUNCTION_TRACE_U32(name, value) \ + ACPI_TRACE_ENTRY (name, acpi_ut_trace_u32, (u32), value) + +#define ACPI_FUNCTION_TRACE_STR(name, string) \ + ACPI_TRACE_ENTRY (name, acpi_ut_trace_str, (char *), string) + +#define ACPI_FUNCTION_ENTRY() \ + acpi_ut_track_stack_ptr() + +/* + * Function exit tracing + * + * These macros include a return statement. This is usually considered + * bad form, but having a separate exit macro before the actual return + * is very ugly and difficult to maintain. + * + * One of the FUNCTION_TRACE macros above must be used in conjunction + * with these macros so that "_AcpiFunctionName" is defined. + */ + +/* Exit trace helper macro */ + +#define ACPI_TRACE_EXIT(function, cast, param) \ + ACPI_DO_WHILE0 ({ \ + function (ACPI_DEBUG_PARAMETERS, cast (param)); \ + return ((param)); \ + }) + +/* The actual exit macros */ + +#define return_VOID \ + ACPI_DO_WHILE0 ({ \ + acpi_ut_exit (ACPI_DEBUG_PARAMETERS); \ + return; \ + }) + +#define return_ACPI_STATUS(status) \ + ACPI_TRACE_EXIT (acpi_ut_status_exit, (acpi_status), status) + +#define return_PTR(pointer) \ + ACPI_TRACE_EXIT (acpi_ut_ptr_exit, (u8 *), pointer) + +#define return_VALUE(value) \ + ACPI_TRACE_EXIT (acpi_ut_value_exit, (u64), value) + +/* Conditional execution */ + +#define ACPI_DEBUG_EXEC(a) a +#define ACPI_DEBUG_ONLY_MEMBERS(a) a; +#define _VERBOSE_STRUCTURES + +/* Various object display routines for debug */ + +#define ACPI_DUMP_STACK_ENTRY(a) acpi_ex_dump_operand((a), 0) +#define ACPI_DUMP_OPERANDS(a, b ,c) acpi_ex_dump_operands(a, b, c) +#define ACPI_DUMP_ENTRY(a, b) acpi_ns_dump_entry (a, b) +#define ACPI_DUMP_PATHNAME(a, b, c, d) acpi_ns_dump_pathname(a, b, c, d) +#define ACPI_DUMP_BUFFER(a, b) acpi_ut_debug_dump_buffer((u8 *) a, b, DB_BYTE_DISPLAY, _COMPONENT) + +#else /* ACPI_DEBUG_OUTPUT */ /* * This is the non-debug case -- make everything go away, * leaving no executable debug code! @@ -281,6 +404,32 @@ #define ACPI_FUNCTION_NAME(a) #define ACPI_DEBUG_PRINT(pl) #define ACPI_DEBUG_PRINT_RAW(pl) +#define ACPI_DEBUG_EXEC(a) +#define ACPI_DEBUG_ONLY_MEMBERS(a) +#define ACPI_FUNCTION_TRACE(a) +#define ACPI_FUNCTION_TRACE_PTR(a, b) +#define ACPI_FUNCTION_TRACE_U32(a, b) +#define ACPI_FUNCTION_TRACE_STR(a, b) +#define ACPI_FUNCTION_EXIT +#define ACPI_FUNCTION_STATUS_EXIT(s) +#define ACPI_FUNCTION_VALUE_EXIT(s) +#define ACPI_FUNCTION_ENTRY() +#define ACPI_DUMP_STACK_ENTRY(a) +#define ACPI_DUMP_OPERANDS(a, b, c) +#define ACPI_DUMP_ENTRY(a, b) +#define ACPI_DUMP_TABLES(a, b) +#define ACPI_DUMP_PATHNAME(a, b, c, d) +#define ACPI_DUMP_BUFFER(a, b) +#define ACPI_DEBUG_PRINT(pl) +#define ACPI_DEBUG_PRINT_RAW(pl) +#define ACPI_IS_DEBUG_ENABLED(level, component) 0 + +/* Return macros must have a return statement at the minimum */ + +#define return_VOID return +#define return_ACPI_STATUS(s) return(s) +#define return_VALUE(s) return(s) +#define return_PTR(s) return(s) #endif /* ACPI_DEBUG_OUTPUT */ diff --git a/include/acpi/acpi.h b/include/acpi/acpi.h index c1ea8436961fea8385d7845e2905e1331efa0826..618787715d560c4162ec15f4351c80391436f203 100644 --- a/include/acpi/acpi.h +++ b/include/acpi/acpi.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 7ced5dc20dd3b98adbfb990bd5962b6d4ee94237..227ba7dc293d0f334e4d56de92189022200badd2 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -83,29 +83,30 @@ enum acpi_bus_device_type { struct acpi_driver; struct acpi_device; +/* + * ACPI Scan Handler + * ----------------- + */ + +struct acpi_scan_handler { + const struct acpi_device_id *ids; + struct list_head list_node; + int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id); + void (*detach)(struct acpi_device *dev); +}; + /* * ACPI Driver * ----------- */ typedef int (*acpi_op_add) (struct acpi_device * device); -typedef int (*acpi_op_remove) (struct acpi_device * device, int type); -typedef int (*acpi_op_start) (struct acpi_device * device); -typedef int (*acpi_op_bind) (struct acpi_device * device); -typedef int (*acpi_op_unbind) (struct acpi_device * device); +typedef int (*acpi_op_remove) (struct acpi_device * device); typedef void (*acpi_op_notify) (struct acpi_device * device, u32 event); -struct acpi_bus_ops { - u32 acpi_op_add:1; - u32 acpi_op_start:1; -}; - struct acpi_device_ops { acpi_op_add add; acpi_op_remove remove; - acpi_op_start start; - acpi_op_bind bind; - acpi_op_unbind unbind; acpi_op_notify notify; }; @@ -148,7 +149,8 @@ struct acpi_device_flags { u32 power_manageable:1; u32 performance_manageable:1; u32 eject_pending:1; - u32 reserved:24; + u32 match_driver:1; + u32 reserved:23; }; /* File System */ @@ -207,7 +209,7 @@ struct acpi_device_power_state { } flags; int power; /* % Power (compared to D0) */ int latency; /* Dx->D0 time (microseconds) */ - struct acpi_handle_list resources; /* Power resources referenced */ + struct list_head resources; /* Power resources referenced */ }; struct acpi_device_power { @@ -250,7 +252,7 @@ struct acpi_device_wakeup { acpi_handle gpe_device; u64 gpe_number; u64 sleep_state; - struct acpi_handle_list resources; + struct list_head resources; struct acpi_device_wakeup_flags flags; int prepare_count; }; @@ -279,16 +281,17 @@ struct acpi_device { struct acpi_device_wakeup wakeup; struct acpi_device_perf performance; struct acpi_device_dir dir; - struct acpi_device_ops ops; + struct acpi_scan_handler *handler; struct acpi_driver *driver; void *driver_data; struct device dev; - struct acpi_bus_ops bus_ops; /* workaround for different code path for hotplug */ enum acpi_bus_removal_type removal_type; /* indicate for different removal type */ u8 physical_node_count; struct list_head physical_node_list; struct mutex physical_node_lock; DECLARE_BITMAP(physical_node_id_bitmap, ACPI_MAX_PHYSICAL_NODE); + struct list_head power_dependent; + void (*remove)(struct acpi_device *); }; static inline void *acpi_driver_data(struct acpi_device *d) @@ -316,7 +319,7 @@ struct acpi_bus_event { }; struct acpi_eject_event { - acpi_handle handle; + struct acpi_device *device; u32 event; }; @@ -339,13 +342,51 @@ void acpi_bus_data_handler(acpi_handle handle, void *context); acpi_status acpi_bus_get_status_handle(acpi_handle handle, unsigned long long *sta); int acpi_bus_get_status(struct acpi_device *device); + +#ifdef CONFIG_PM int acpi_bus_set_power(acpi_handle handle, int state); +const char *acpi_power_state_string(int state); +int acpi_device_get_power(struct acpi_device *device, int *state); int acpi_device_set_power(struct acpi_device *device, int state); +int acpi_bus_init_power(struct acpi_device *device); int acpi_bus_update_power(acpi_handle handle, int *state_p); bool acpi_bus_power_manageable(acpi_handle handle); bool acpi_bus_can_wakeup(acpi_handle handle); -int acpi_power_resource_register_device(struct device *dev, acpi_handle handle); -void acpi_power_resource_unregister_device(struct device *dev, acpi_handle handle); +#else /* !CONFIG_PM */ +static inline int acpi_bus_set_power(acpi_handle handle, int state) +{ + return 0; +} +static inline const char *acpi_power_state_string(int state) +{ + return "D0"; +} +static inline int acpi_device_get_power(struct acpi_device *device, int *state) +{ + return 0; +} +static inline int acpi_device_set_power(struct acpi_device *device, int state) +{ + return 0; +} +static inline int acpi_bus_init_power(struct acpi_device *device) +{ + return 0; +} +static inline int acpi_bus_update_power(acpi_handle handle, int *state_p) +{ + return 0; +} +static inline bool acpi_bus_power_manageable(acpi_handle handle) +{ + return false; +} +static inline bool acpi_bus_can_wakeup(acpi_handle handle) +{ + return false; +} +#endif /* !CONFIG_PM */ + #ifdef CONFIG_ACPI_PROC_EVENT int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data); int acpi_bus_generate_proc_event4(const char *class, const char *bid, u8 type, int data); @@ -354,13 +395,15 @@ int acpi_bus_receive_event(struct acpi_bus_event *event); static inline int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data) { return 0; } #endif + +void acpi_scan_lock_acquire(void); +void acpi_scan_lock_release(void); +int acpi_scan_add_handler(struct acpi_scan_handler *handler); int acpi_bus_register_driver(struct acpi_driver *driver); void acpi_bus_unregister_driver(struct acpi_driver *driver); -int acpi_bus_add(struct acpi_device **child, struct acpi_device *parent, - acpi_handle handle, int type); +int acpi_bus_scan(acpi_handle handle); void acpi_bus_hot_remove_device(void *context); -int acpi_bus_trim(struct acpi_device *start, int rmdevice); -int acpi_bus_start(struct acpi_device *device); +void acpi_bus_trim(struct acpi_device *start); acpi_status acpi_bus_get_ejd(acpi_handle handle, acpi_handle * ejd); int acpi_match_device_ids(struct acpi_device *device, const struct acpi_device_id *ids); @@ -390,6 +433,8 @@ struct acpi_bus_type { int (*find_device) (struct device *, acpi_handle *); /* For bridges, such as PCI root bridge, IDE controller */ int (*find_bridge) (struct device *, acpi_handle *); + void (*setup)(struct device *); + void (*cleanup)(struct device *); }; int register_acpi_bus_type(struct acpi_bus_type *); int unregister_acpi_bus_type(struct acpi_bus_type *); @@ -397,7 +442,6 @@ int unregister_acpi_bus_type(struct acpi_bus_type *); struct acpi_pci_root { struct list_head node; struct acpi_device * device; - struct acpi_pci_id id; struct pci_bus *bus; u16 segment; struct resource secondary; /* downstream bus range */ @@ -425,6 +469,8 @@ acpi_status acpi_remove_pm_notifier(struct acpi_device *adev, int acpi_device_power_state(struct device *dev, struct acpi_device *adev, u32 target_state, int d_max_in, int *d_min_p); int acpi_pm_device_sleep_state(struct device *, int *, int); +void acpi_dev_pm_add_dependent(acpi_handle handle, struct device *depdev); +void acpi_dev_pm_remove_dependent(acpi_handle handle, struct device *depdev); #else static inline acpi_status acpi_add_pm_notifier(struct acpi_device *adev, acpi_notify_handler handler, @@ -454,6 +500,10 @@ static inline int acpi_pm_device_sleep_state(struct device *d, int *p, int m) { return __acpi_device_power_state(m, p); } +static inline void acpi_dev_pm_add_dependent(acpi_handle handle, + struct device *depdev) {} +static inline void acpi_dev_pm_remove_dependent(acpi_handle handle, + struct device *depdev) {} #endif #ifdef CONFIG_PM_RUNTIME diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h index 43152742b46fe8e56a8731dbcdb79a9c8e6ab79b..7d2a9eaab9ebaf254b7d108c99af9c3d0a2d45e0 100644 --- a/include/acpi/acpiosxf.h +++ b/include/acpi/acpiosxf.h @@ -7,7 +7,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -102,10 +102,8 @@ acpi_os_physical_table_override(struct acpi_table_header *existing_table, /* * Spinlock primitives */ - #ifndef acpi_os_create_lock -acpi_status -acpi_os_create_lock(acpi_spinlock *out_handle); +acpi_status acpi_os_create_lock(acpi_spinlock * out_handle); #endif void acpi_os_delete_lock(acpi_spinlock handle); @@ -148,6 +146,8 @@ void acpi_os_release_mutex(acpi_mutex handle); */ void *acpi_os_allocate(acpi_size size); +void acpi_os_free(void *memory); + void __iomem *acpi_os_map_memory(acpi_physical_address where, acpi_size length); @@ -180,12 +180,13 @@ acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object); * Interrupt handlers */ acpi_status -acpi_os_install_interrupt_handler(u32 gsi, +acpi_os_install_interrupt_handler(u32 interrupt_number, acpi_osd_handler service_routine, void *context); acpi_status -acpi_os_remove_interrupt_handler(u32 gsi, acpi_osd_handler service_routine); +acpi_os_remove_interrupt_handler(u32 interrupt_number, + acpi_osd_handler service_routine); void acpi_os_gpe_count(u32 gpe_number); void acpi_os_fixed_event_count(u32 fixed_event_number); diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 3d88395d4d6fbc47ff93dd98d3747dd408058679..03322dddd88ead0b18b0c9aaf11e43fdf763257a 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -46,7 +46,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20121018 +#define ACPI_CA_VERSION 0x20130117 #include #include @@ -56,11 +56,20 @@ extern u8 acpi_gbl_permanent_mmap; /* - * Globals that are publicly available, allowing for - * run time configuration + * Globals that are publically available */ +extern u32 acpi_current_gpe_count; +extern struct acpi_table_fadt acpi_gbl_FADT; +extern u8 acpi_gbl_system_awake_and_running; +extern u8 acpi_gbl_reduced_hardware; /* ACPI 5.0 */ + +/* Runtime configuration of debug print levels */ + extern u32 acpi_dbg_level; extern u32 acpi_dbg_layer; + +/* ACPICA runtime options */ + extern u8 acpi_gbl_enable_interpreter_slack; extern u8 acpi_gbl_all_methods_serialized; extern u8 acpi_gbl_create_osi_method; @@ -99,14 +108,9 @@ extern u8 acpi_gbl_disable_auto_repair; #endif /* !ACPI_REDUCED_HARDWARE */ -extern u32 acpi_current_gpe_count; -extern struct acpi_table_fadt acpi_gbl_FADT; -extern u8 acpi_gbl_system_awake_and_running; -extern u8 acpi_gbl_reduced_hardware; /* ACPI 5.0 */ - extern u32 acpi_rsdt_forced; /* - * Global interfaces + * Initialization */ acpi_status acpi_initialize_tables(struct acpi_table_desc *initial_storage, @@ -120,13 +124,15 @@ acpi_status acpi_initialize_objects(u32 flags); acpi_status acpi_terminate(void); +/* + * Miscellaneous global interfaces + */ +ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable(void)) +ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_disable(void)) #ifdef ACPI_FUTURE_USAGE acpi_status acpi_subsystem_status(void); #endif -ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable(void)) -ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_disable(void)) - #ifdef ACPI_FUTURE_USAGE acpi_status acpi_get_system_info(struct acpi_buffer *ret_buffer); #endif @@ -191,9 +197,9 @@ acpi_status acpi_get_table_by_index(u32 table_index, struct acpi_table_header **out_table); acpi_status -acpi_install_table_handler(acpi_tbl_handler handler, void *context); +acpi_install_table_handler(acpi_table_handler handler, void *context); -acpi_status acpi_remove_table_handler(acpi_tbl_handler handler); +acpi_status acpi_remove_table_handler(acpi_table_handler handler); /* * Namespace and name interfaces @@ -437,6 +443,11 @@ acpi_status acpi_get_event_resources(acpi_handle device_handle, struct acpi_buffer *ret_buffer); +acpi_status +acpi_walk_resource_buffer(struct acpi_buffer *buffer, + acpi_walk_resource_callback user_function, + void *context); + acpi_status acpi_walk_resources(acpi_handle device, char *name, @@ -462,6 +473,10 @@ acpi_buffer_to_resource(u8 *aml_buffer, */ acpi_status acpi_reset(void); +acpi_status acpi_read(u64 *value, struct acpi_generic_address *reg); + +acpi_status acpi_write(u64 value, struct acpi_generic_address *reg); + ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_read_bit_register(u32 register_id, u32 *return_value)) @@ -470,20 +485,6 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_write_bit_register(u32 register_id, u32 value)) -ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status - acpi_set_firmware_waking_vector(u32 - physical_address)) - -#if ACPI_MACHINE_WIDTH == 64 -ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status - acpi_set_firmware_waking_vector64(u64 - physical_address)) -#endif - -acpi_status acpi_read(u64 *value, struct acpi_generic_address *reg); - -acpi_status acpi_write(u64 value, struct acpi_generic_address *reg); - /* * Sleep/Wake interfaces */ @@ -500,6 +501,15 @@ acpi_status acpi_leave_sleep_state_prep(u8 sleep_state); acpi_status acpi_leave_sleep_state(u8 sleep_state); +ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status + acpi_set_firmware_waking_vector(u32 + physical_address)) + +#if ACPI_MACHINE_WIDTH == 64 +ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status + acpi_set_firmware_waking_vector64(u64 + physical_address)) +#endif /* * ACPI Timer interfaces */ diff --git a/include/acpi/acrestyp.h b/include/acpi/acrestyp.h index 40349ae654640e249f161c3df888577f19eecdc1..cbf4bf977f75c0483ac9a8fb9211e7d59ff88a6b 100644 --- a/include/acpi/acrestyp.h +++ b/include/acpi/acrestyp.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -102,8 +102,11 @@ typedef u32 acpi_rsdesc_size; /* Max Resource Descriptor size is (Length+3) = (6 #define ACPI_EXCLUSIVE (u8) 0x00 #define ACPI_SHARED (u8) 0x01 -#define ACPI_EXCLUSIVE_AND_WAKE (u8) 0x02 -#define ACPI_SHARED_AND_WAKE (u8) 0x03 + +/* Wake */ + +#define ACPI_NOT_WAKE_CAPABLE (u8) 0x00 +#define ACPI_WAKE_CAPABLE (u8) 0x01 /* * DMA Attributes @@ -171,6 +174,7 @@ struct acpi_resource_irq { u8 triggering; u8 polarity; u8 sharable; + u8 wake_capable; u8 interrupt_count; u8 interrupts[1]; }; @@ -346,6 +350,7 @@ struct acpi_resource_extended_irq { u8 triggering; u8 polarity; u8 sharable; + u8 wake_capable; u8 interrupt_count; struct acpi_resource_source resource_source; u32 interrupts[1]; @@ -365,6 +370,7 @@ struct acpi_resource_gpio { u8 producer_consumer; /* For values, see Producer/Consumer above */ u8 pin_config; u8 sharable; /* For values, see Interrupt Attributes above */ + u8 wake_capable; /* For values, see Interrupt Attributes above */ u8 io_restriction; u8 triggering; /* For values, see Interrupt Attributes above */ u8 polarity; /* For values, see Interrupt Attributes above */ @@ -591,7 +597,10 @@ struct acpi_resource { #define ACPI_RS_SIZE_MIN (u32) ACPI_ROUND_UP_TO_NATIVE_WORD (12) #define ACPI_RS_SIZE(type) (u32) (ACPI_RS_SIZE_NO_DATA + sizeof (type)) -#define ACPI_NEXT_RESOURCE(res) (struct acpi_resource *)((u8 *) res + res->length) +/* Macro for walking resource templates with multiple descriptors */ + +#define ACPI_NEXT_RESOURCE(res) \ + ACPI_ADD_PTR (struct acpi_resource, (res), (res)->length) struct acpi_pci_routing_table { u32 length; diff --git a/include/acpi/actbl.h b/include/acpi/actbl.h index 4f94b1d812d5a7af89abbcda02ae4adf9924e42f..9b58a8f4377127f198498e7db54430cf9c5979ae 100644 --- a/include/acpi/actbl.h +++ b/include/acpi/actbl.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -326,8 +326,6 @@ enum acpi_preferred_pm_profiles { #pragma pack() -#define ACPI_FADT_OFFSET(f) (u16) ACPI_OFFSET (struct acpi_table_fadt, f) - /* * Internal table-related structures */ @@ -359,11 +357,14 @@ struct acpi_table_desc { /* * Get the remaining ACPI tables */ - #include #include #include +/* Macros used to generate offsets to specific table fields */ + +#define ACPI_FADT_OFFSET(f) (u16) ACPI_OFFSET (struct acpi_table_fadt, f) + /* * Sizes of the various flavors of FADT. We need to look closely * at the FADT length because the version number essentially tells diff --git a/include/acpi/actbl1.h b/include/acpi/actbl1.h index 280fc45b59dde399ca5c646c9dae553b3aa16591..0bd750ebeb491c5b026c7f62811d1311ff08d310 100644 --- a/include/acpi/actbl1.h +++ b/include/acpi/actbl1.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -768,7 +768,7 @@ struct acpi_madt_interrupt_source { struct acpi_madt_local_x2apic { struct acpi_subtable_header header; - u16 reserved; /* Reserved - must be zero */ + u16 reserved; /* reserved - must be zero */ u32 local_apic_id; /* Processor x2APIC ID */ u32 lapic_flags; u32 uid; /* ACPI processor UID */ @@ -781,14 +781,14 @@ struct acpi_madt_local_x2apic_nmi { u16 inti_flags; u32 uid; /* ACPI processor UID */ u8 lint; /* LINTn to which NMI is connected */ - u8 reserved[3]; + u8 reserved[3]; /* reserved - must be zero */ }; /* 11: Generic Interrupt (ACPI 5.0) */ struct acpi_madt_generic_interrupt { struct acpi_subtable_header header; - u16 reserved; /* Reserved - must be zero */ + u16 reserved; /* reserved - must be zero */ u32 gic_id; u32 uid; u32 flags; diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h index 1b2b356486d1637651607ae01a76e0917e7d7539..77dc7a4099a3542d98ab231ce80908db108a96d2 100644 --- a/include/acpi/actbl2.h +++ b/include/acpi/actbl2.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -261,9 +261,28 @@ struct acpi_csrt_group { u16 subdevice_id; u16 revision; u16 reserved; - u32 info_length; + u32 shared_info_length; - /* Shared data (length = info_length) immediately follows */ + /* Shared data immediately follows (Length = shared_info_length) */ +}; + +/* Shared Info subtable */ + +struct acpi_csrt_shared_info { + u16 major_version; + u16 minor_version; + u32 mmio_base_low; + u32 mmio_base_high; + u32 gsi_interrupt; + u8 interrupt_polarity; + u8 interrupt_mode; + u8 num_channels; + u8 dma_address_width; + u16 base_request_line; + u16 num_handshake_signals; + u32 max_block_size; + + /* Resource descriptors immediately follow (Length = Group length - shared_info_length) */ }; /* Resource Descriptor subtable */ diff --git a/include/acpi/actbl3.h b/include/acpi/actbl3.h index 6585141e4b97e1dafe342f4fc200786ece1b70dd..332b17e3bec80152a83400e772a0ae280d5d19be 100644 --- a/include/acpi/actbl3.h +++ b/include/acpi/actbl3.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -68,13 +68,13 @@ #define ACPI_SIG_PCCT "PCCT" /* Platform Communications Channel Table */ #define ACPI_SIG_PMTT "PMTT" /* Platform Memory Topology Table */ #define ACPI_SIG_RASF "RASF" /* RAS Feature table */ +#define ACPI_SIG_TPM2 "TPM2" /* Trusted Platform Module 2.0 H/W interface table */ #define ACPI_SIG_S3PT "S3PT" /* S3 Performance (sub)Table */ #define ACPI_SIG_PCCS "PCC" /* PCC Shared Memory Region */ /* Reserved table signatures */ -#define ACPI_SIG_CSRT "CSRT" /* Core System Resources Table */ #define ACPI_SIG_MATR "MATR" /* Memory Address Translation Table */ #define ACPI_SIG_MSDM "MSDM" /* Microsoft Data Management Table */ #define ACPI_SIG_WPBT "WPBT" /* Windows Platform Binary Table */ @@ -550,6 +550,36 @@ enum acpi_rasf_status { #define ACPI_RASF_ERROR (1<<2) #define ACPI_RASF_STATUS (0x1F<<3) +/******************************************************************************* + * + * TPM2 - Trusted Platform Module (TPM) 2.0 Hardware Interface Table + * Version 3 + * + * Conforms to "TPM 2.0 Hardware Interface Table (TPM2)" 29 November 2011 + * + ******************************************************************************/ + +struct acpi_table_tpm2 { + struct acpi_table_header header; /* Common ACPI table header */ + u32 flags; + u64 control_address; + u32 start_method; +}; + +/* Control area structure (not part of table, pointed to by control_address) */ + +struct acpi_tpm2_control { + u32 reserved; + u32 error; + u32 cancel; + u32 start; + u64 interrupt_control; + u32 command_size; + u64 command_address; + u32 response_size; + u64 response_address; +}; + /* Reset to default packing */ #pragma pack() diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index 4f43f1fba132fff7cd303ecf6cd0c283a778e3d1..845e75f1ffd89eabcb06fb7f0431f3bc21495145 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -341,7 +341,7 @@ typedef u32 acpi_physical_address; /* PM Timer ticks per second (HZ) */ -#define PM_TIMER_FREQUENCY 3579545 +#define ACPI_PM_TIMER_FREQUENCY 3579545 /******************************************************************************* * @@ -373,6 +373,21 @@ typedef u32 acpi_name; /* 4-byte ACPI name */ typedef char *acpi_string; /* Null terminated ASCII string */ typedef void *acpi_handle; /* Actually a ptr to a NS Node */ +/* Time constants for timer calculations */ + +#define ACPI_MSEC_PER_SEC 1000L + +#define ACPI_USEC_PER_MSEC 1000L +#define ACPI_USEC_PER_SEC 1000000L + +#define ACPI_100NSEC_PER_USEC 10L +#define ACPI_100NSEC_PER_MSEC 10000L +#define ACPI_100NSEC_PER_SEC 10000000L + +#define ACPI_NSEC_PER_USEC 1000L +#define ACPI_NSEC_PER_MSEC 1000000L +#define ACPI_NSEC_PER_SEC 1000000000L + /* Owner IDs are used to track namespace nodes for selective deletion */ typedef u8 acpi_owner_id; @@ -390,10 +405,6 @@ typedef u8 acpi_owner_id; #define ACPI_MAX16_DECIMAL_DIGITS 5 #define ACPI_MAX8_DECIMAL_DIGITS 3 -/* PM Timer ticks per second (HZ) */ - -#define PM_TIMER_FREQUENCY 3579545 - /* * Constants with special meanings */ @@ -474,6 +485,7 @@ typedef u64 acpi_integer; */ #define ACPI_FULL_INITIALIZATION 0x00 #define ACPI_NO_ADDRESS_SPACE_INIT 0x01 +#define ACPI_NO_HARDWARE_INIT 0x02 #define ACPI_NO_EVENT_INIT 0x04 #define ACPI_NO_HANDLER_INIT 0x08 #define ACPI_NO_ACPI_ENABLE 0x10 @@ -595,7 +607,7 @@ typedef u32 acpi_object_type; /* * These are special object types that never appear in - * a Namespace node, only in a union acpi_operand_object + * a Namespace node, only in an object of union acpi_operand_object */ #define ACPI_TYPE_LOCAL_EXTRA 0x1C #define ACPI_TYPE_LOCAL_DATA 0x1D @@ -662,7 +674,7 @@ typedef u32 acpi_event_status; #define ACPI_GPE_MAX 0xFF #define ACPI_NUM_GPE 256 -/* Actions for acpi_set_gpe_wake_mask, acpi_hw_low_set_gpe */ +/* Actions for acpi_set_gpe, acpi_gpe_wakeup, acpi_hw_low_set_gpe */ #define ACPI_GPE_ENABLE 0 #define ACPI_GPE_DISABLE 1 @@ -880,6 +892,10 @@ struct acpi_buffer { void *pointer; /* pointer to buffer */ }; +/* Free a buffer created in an struct acpi_buffer via ACPI_ALLOCATE_LOCAL_BUFFER */ + +#define ACPI_FREE_BUFFER(b) ACPI_FREE(b.pointer) + /* * name_type for acpi_get_name */ @@ -968,7 +984,11 @@ acpi_status(*acpi_exception_handler) (acpi_status aml_status, /* Table Event handler (Load, load_table, etc.) and types */ typedef -acpi_status(*acpi_tbl_handler) (u32 event, void *table, void *context); +acpi_status(*acpi_table_handler) (u32 event, void *table, void *context); + +#define ACPI_TABLE_LOAD 0x0 +#define ACPI_TABLE_UNLOAD 0x1 +#define ACPI_NUM_TABLE_EVENTS 2 /* Address Spaces (For Operation Regions) */ diff --git a/include/acpi/container.h b/include/acpi/container.h deleted file mode 100644 index a703f14e049eeadd9cab2ee5dc8504c6726e8e93..0000000000000000000000000000000000000000 --- a/include/acpi/container.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef __ACPI_CONTAINER_H -#define __ACPI_CONTAINER_H - -#include - -struct acpi_container { - acpi_handle handle; - unsigned long sun; - int state; -}; - -#endif /* __ACPI_CONTAINER_H */ diff --git a/include/acpi/platform/acenv.h b/include/acpi/platform/acenv.h index 89cee88dd2a56e0d84eec0018381abeafa14dc30..ef04b36ca6ed788de2e4b8c305508a2f9d165f3f 100644 --- a/include/acpi/platform/acenv.h +++ b/include/acpi/platform/acenv.h @@ -1,11 +1,11 @@ /****************************************************************************** * - * Name: acenv.h - Generation environment specific items + * Name: acenv.h - Host and compiler configuration * *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,6 +44,12 @@ #ifndef __ACENV_H__ #define __ACENV_H__ +/* + * Environment configuration. The purpose of this file is to interface ACPICA + * to the local environment. This includes compiler-specific, OS-specific, + * and machine-specific configuration. + */ + /* Types for ACPI_MUTEX_TYPE */ #define ACPI_BINARY_SEMAPHORE 0 @@ -60,145 +66,200 @@ * *****************************************************************************/ -#ifdef ACPI_LIBRARY -/* - * Note: The non-debug version of the acpi_library does not contain any - * debug support, for minimal size. The debug version uses ACPI_FULL_DEBUG - */ -#define ACPI_USE_LOCAL_CACHE -#endif +/* iASL configuration */ #ifdef ACPI_ASL_COMPILER -#define ACPI_DEBUG_OUTPUT #define ACPI_APPLICATION #define ACPI_DISASSEMBLER +#define ACPI_DEBUG_OUTPUT #define ACPI_CONSTANT_EVAL_ONLY #define ACPI_LARGE_NAMESPACE_NODE #define ACPI_DATA_TABLE_DISASSEMBLY +#define ACPI_SINGLE_THREADED #endif +/* acpi_exec configuration. Multithreaded with full AML debugger */ + #ifdef ACPI_EXEC_APP -#undef DEBUGGER_THREADING -#define DEBUGGER_THREADING DEBUGGER_SINGLE_THREADED -#define ACPI_FULL_DEBUG #define ACPI_APPLICATION -#define ACPI_DEBUGGER +#define ACPI_FULL_DEBUG #define ACPI_MUTEX_DEBUG #define ACPI_DBG_TRACK_ALLOCATIONS #endif +/* acpi_names configuration. Single threaded with debugger output enabled. */ + +#ifdef ACPI_NAMES_APP +#define ACPI_DEBUGGER +#define ACPI_APPLICATION +#define ACPI_SINGLE_THREADED +#endif + +/* + * acpi_bin/acpi_help/acpi_src configuration. All single threaded, with + * no debug output. + */ +#if (defined ACPI_BIN_APP) || \ + (defined ACPI_SRC_APP) || \ + (defined ACPI_XTRACT_APP) +#define ACPI_APPLICATION +#define ACPI_SINGLE_THREADED +#endif + +#ifdef ACPI_HELP_APP +#define ACPI_APPLICATION +#define ACPI_SINGLE_THREADED +#define ACPI_NO_ERROR_MESSAGES +#endif + +/* Linkable ACPICA library */ + +#ifdef ACPI_LIBRARY +#define ACPI_USE_LOCAL_CACHE +#define ACPI_FUTURE_USAGE +#endif + +/* Common for all ACPICA applications */ + #ifdef ACPI_APPLICATION #define ACPI_USE_SYSTEM_CLIBRARY #define ACPI_USE_LOCAL_CACHE #endif +/* Common debug support */ + #ifdef ACPI_FULL_DEBUG #define ACPI_DEBUGGER #define ACPI_DEBUG_OUTPUT #define ACPI_DISASSEMBLER #endif -/* - * Environment configuration. The purpose of this file is to interface to the - * local generation environment. - * - * 1) ACPI_USE_SYSTEM_CLIBRARY - Define this if linking to an actual C library. - * Otherwise, local versions of string/memory functions will be used. - * 2) ACPI_USE_STANDARD_HEADERS - Define this if linking to a C library and - * the standard header files may be used. - * - * The ACPI subsystem only uses low level C library functions that do not call - * operating system services and may therefore be inlined in the code. - * - * It may be necessary to tailor these include files to the target - * generation environment. - * - * - * Functions and constants used from each header: - * - * string.h: memcpy - * memset - * strcat - * strcmp - * strcpy - * strlen - * strncmp - * strncat - * strncpy - * - * stdlib.h: strtoul - * - * stdarg.h: va_list - * va_arg - * va_start - * va_end - * - */ /*! [Begin] no source code translation */ +/****************************************************************************** + * + * Host configuration files. The compiler configuration files are included + * by the host files. + * + *****************************************************************************/ + #if defined(_LINUX) || defined(__linux__) #include -#elif defined(_AED_EFI) -#include "acefi.h" - -#elif defined(WIN32) -#include "acwin.h" - -#elif defined(WIN64) -#include "acwin64.h" - -#elif defined(MSDOS) /* Must appear after WIN32 and WIN64 check */ -#include "acdos16.h" - #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) #include "acfreebsd.h" #elif defined(__NetBSD__) #include "acnetbsd.h" +#elif defined(__sun) +#include "acsolaris.h" + #elif defined(MODESTO) #include "acmodesto.h" #elif defined(NETWARE) #include "acnetware.h" -#elif defined(__sun) -#include "acsolaris.h" +#elif defined(_CYGWIN) +#include "accygwin.h" -#else +#elif defined(WIN32) +#include "acwin.h" + +#elif defined(WIN64) +#include "acwin64.h" -/* All other environments */ +#elif defined(_WRS_LIB_BUILD) +#include "acvxworks.h" -#define ACPI_USE_STANDARD_HEADERS +#elif defined(__OS2__) +#include "acos2.h" -#define COMPILER_DEPENDENT_INT64 long long -#define COMPILER_DEPENDENT_UINT64 unsigned long long +#elif defined(_AED_EFI) +#include "acefi.h" + +#elif defined(__HAIKU__) +#include "achaiku.h" +#else + +/* Unknown environment */ + +#error Unknown target environment #endif /*! [End] no source code translation !*/ /****************************************************************************** * - * Miscellaneous configuration + * Setup defaults for the required symbols that were not defined in one of + * the host/compiler files above. * *****************************************************************************/ -/* - * Are mutexes supported by the host? default is no, use binary semaphores. - */ +/* 64-bit data types */ + +#ifndef COMPILER_DEPENDENT_INT64 +#define COMPILER_DEPENDENT_INT64 long long +#endif + +#ifndef COMPILER_DEPENDENT_UINT64 +#define COMPILER_DEPENDENT_UINT64 unsigned long long +#endif + +/* Type of mutex supported by host. Default is binary semaphores. */ #ifndef ACPI_MUTEX_TYPE #define ACPI_MUTEX_TYPE ACPI_BINARY_SEMAPHORE #endif +/* Global Lock acquire/release */ + +#ifndef ACPI_ACQUIRE_GLOBAL_LOCK +#define ACPI_ACQUIRE_GLOBAL_LOCK(Glptr, acquired) acquired = 1 +#endif + +#ifndef ACPI_RELEASE_GLOBAL_LOCK +#define ACPI_RELEASE_GLOBAL_LOCK(Glptr, pending) pending = 0 +#endif + +/* Flush CPU cache - used when going to sleep. Wbinvd or similar. */ + +#ifndef ACPI_FLUSH_CPU_CACHE +#define ACPI_FLUSH_CPU_CACHE() +#endif + /* "inline" keywords - configurable since inline is not standardized */ #ifndef ACPI_INLINE #define ACPI_INLINE #endif +/* + * Configurable calling conventions: + * + * ACPI_SYSTEM_XFACE - Interfaces to host OS (handlers, threads) + * ACPI_EXTERNAL_XFACE - External ACPI interfaces + * ACPI_INTERNAL_XFACE - Internal ACPI interfaces + * ACPI_INTERNAL_VAR_XFACE - Internal variable-parameter list interfaces + */ +#ifndef ACPI_SYSTEM_XFACE +#define ACPI_SYSTEM_XFACE +#endif + +#ifndef ACPI_EXTERNAL_XFACE +#define ACPI_EXTERNAL_XFACE +#endif + +#ifndef ACPI_INTERNAL_XFACE +#define ACPI_INTERNAL_XFACE +#endif + +#ifndef ACPI_INTERNAL_VAR_XFACE +#define ACPI_INTERNAL_VAR_XFACE +#endif + /* * Debugger threading model * Use single threaded if the entire subsystem is contained in an application @@ -222,17 +283,26 @@ * *****************************************************************************/ -#define ACPI_IS_ASCII(c) ((c) < 0x80) - -#ifdef ACPI_USE_SYSTEM_CLIBRARY /* - * Use the standard C library headers. - * We want to keep these to a minimum. + * ACPI_USE_SYSTEM_CLIBRARY - Define this if linking to an actual C library. + * Otherwise, local versions of string/memory functions will be used. + * ACPI_USE_STANDARD_HEADERS - Define this if linking to a C library and + * the standard header files may be used. + * + * The ACPICA subsystem only uses low level C library functions that do not call + * operating system services and may therefore be inlined in the code. + * + * It may be necessary to tailor these include files to the target + * generation environment. */ +#ifdef ACPI_USE_SYSTEM_CLIBRARY + +/* Use the standard C library headers. We want to keep these to a minimum. */ + #ifdef ACPI_USE_STANDARD_HEADERS -/* - * Use the standard headers from the standard locations - */ + +/* Use the standard headers from the standard locations */ + #include #include #include @@ -240,9 +310,8 @@ #endif /* ACPI_USE_STANDARD_HEADERS */ -/* - * We will be linking to the standard Clib functions - */ +/* We will be linking to the standard Clib functions */ + #define ACPI_STRSTR(s1,s2) strstr((s1), (s2)) #define ACPI_STRCHR(s1,c) strchr((s1), (c)) #define ACPI_STRLEN(s) (acpi_size) strlen((s)) @@ -274,13 +343,12 @@ * *****************************************************************************/ - /* - * Use local definitions of C library macros and functions - * NOTE: The function implementations may not be as efficient - * as an inline or assembly code implementation provided by a - * native C library. - */ - +/* + * Use local definitions of C library macros and functions. These function + * implementations may not be as efficient as an inline or assembly code + * implementation provided by a native C library, but they are functionally + * equivalent. + */ #ifndef va_arg #ifndef _VALIST @@ -288,22 +356,22 @@ typedef char *va_list; #endif /* _VALIST */ -/* - * Storage alignment properties - */ +/* Storage alignment properties */ + #define _AUPBND (sizeof (acpi_native_int) - 1) #define _ADNBND (sizeof (acpi_native_int) - 1) -/* - * Variable argument list macro definitions - */ +/* Variable argument list macro definitions */ + #define _bnd(X, bnd) (((sizeof (X)) + (bnd)) & (~(bnd))) #define va_arg(ap, T) (*(T *)(((ap) += (_bnd (T, _AUPBND))) - (_bnd (T,_ADNBND)))) -#define va_end(ap) (void) 0 +#define va_end(ap) (ap = (va_list) NULL) #define va_start(ap, A) (void) ((ap) = (((char *) &(A)) + (_bnd (A,_AUPBND)))) #endif /* va_arg */ +/* Use the local (ACPICA) definitions of the clib functions */ + #define ACPI_STRSTR(s1,s2) acpi_ut_strstr ((s1), (s2)) #define ACPI_STRCHR(s1,c) acpi_ut_strchr ((s1), (c)) #define ACPI_STRLEN(s) (acpi_size) acpi_ut_strlen ((s)) @@ -322,59 +390,4 @@ typedef char *va_list; #endif /* ACPI_USE_SYSTEM_CLIBRARY */ -/****************************************************************************** - * - * Assembly code macros - * - *****************************************************************************/ - -/* - * Handle platform- and compiler-specific assembly language differences. - * These should already have been defined by the platform includes above. - * - * Notes: - * 1) Interrupt 3 is used to break into a debugger - * 2) Interrupts are turned off during ACPI register setup - */ - -/* Unrecognized compiler, use defaults */ - -#ifndef ACPI_ASM_MACROS - -/* - * Calling conventions: - * - * ACPI_SYSTEM_XFACE - Interfaces to host OS (handlers, threads) - * ACPI_EXTERNAL_XFACE - External ACPI interfaces - * ACPI_INTERNAL_XFACE - Internal ACPI interfaces - * ACPI_INTERNAL_VAR_XFACE - Internal variable-parameter list interfaces - */ -#define ACPI_SYSTEM_XFACE -#define ACPI_EXTERNAL_XFACE -#define ACPI_INTERNAL_XFACE -#define ACPI_INTERNAL_VAR_XFACE - -#define ACPI_ASM_MACROS -#define BREAKPOINT3 -#define ACPI_DISABLE_IRQS() -#define ACPI_ENABLE_IRQS() -#define ACPI_ACQUIRE_GLOBAL_LOCK(Glptr, acq) -#define ACPI_RELEASE_GLOBAL_LOCK(Glptr, acq) - -#endif /* ACPI_ASM_MACROS */ - -#ifdef ACPI_APPLICATION - -/* Don't want software interrupts within a ring3 application */ - -#undef BREAKPOINT3 -#define BREAKPOINT3 -#endif - -/****************************************************************************** - * - * Compiler-specific information is contained in the compiler-specific - * headers. - * - *****************************************************************************/ #endif /* __ACENV_H__ */ diff --git a/include/acpi/platform/acgcc.h b/include/acpi/platform/acgcc.h index 72553b0c9f33e297a5e0037ac010f08d11a05720..e077ce6c38ca658756be11c13589d6a2c76f240c 100644 --- a/include/acpi/platform/acgcc.h +++ b/include/acpi/platform/acgcc.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -64,8 +64,4 @@ */ #define ACPI_UNUSED_VAR __attribute__ ((unused)) -#ifdef _ANSI -#define inline -#endif - #endif /* __ACGCC_H__ */ diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h index 85d5d8f38452b54087ecc716b498c3c8de38a1b8..68534ef86ec81a903e09ccd93169baf69b4bb73e 100644 --- a/include/acpi/platform/aclinux.h +++ b/include/acpi/platform/aclinux.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -108,7 +108,6 @@ #include - #ifdef __KERNEL__ #include /* diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 3994d7790b2309d0ff8bc7ba8f518a75fe4ffd7a..bcbdd7484e581404d54be807c034fced32ba45c2 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -74,9 +74,10 @@ enum acpi_address_range_id { /* Table Handlers */ -typedef int (*acpi_table_handler) (struct acpi_table_header *table); +typedef int (*acpi_tbl_table_handler)(struct acpi_table_header *table); -typedef int (*acpi_table_entry_handler) (struct acpi_subtable_header *header, const unsigned long end); +typedef int (*acpi_tbl_entry_handler)(struct acpi_subtable_header *header, + const unsigned long end); #ifdef CONFIG_ACPI_INITRD_TABLE_OVERRIDE void acpi_initrd_override(void *data, size_t size); @@ -95,10 +96,14 @@ int acpi_mps_check (void); int acpi_numa_init (void); int acpi_table_init (void); -int acpi_table_parse (char *id, acpi_table_handler handler); +int acpi_table_parse(char *id, acpi_tbl_table_handler handler); int __init acpi_table_parse_entries(char *id, unsigned long table_size, - int entry_id, acpi_table_entry_handler handler, unsigned int max_entries); -int acpi_table_parse_madt (enum acpi_madt_type id, acpi_table_entry_handler handler, unsigned int max_entries); + int entry_id, + acpi_tbl_entry_handler handler, + unsigned int max_entries); +int acpi_table_parse_madt(enum acpi_madt_type id, + acpi_tbl_entry_handler handler, + unsigned int max_entries); int acpi_parse_mcfg (struct acpi_table_header *header); void acpi_table_print_madt_entry (struct acpi_subtable_header *madt); @@ -358,8 +363,7 @@ extern acpi_status acpi_pci_osc_control_set(acpi_handle handle, #if defined(CONFIG_ACPI_HOTPLUG_CPU) && \ (defined(CONFIG_ACPI_HOTPLUG_MEMORY) || \ defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE)) && \ - (defined(CONFIG_ACPI_CONTAINER) || \ - defined(CONFIG_ACPI_CONTAINER_MODULE)) + defined(CONFIG_ACPI_CONTAINER) #define ACPI_HOTPLUG_OST #endif @@ -511,7 +515,7 @@ static inline int acpi_subsys_runtime_suspend(struct device *dev) { return 0; } static inline int acpi_subsys_runtime_resume(struct device *dev) { return 0; } #endif -#ifdef CONFIG_ACPI_SLEEP +#if defined(CONFIG_ACPI) && defined(CONFIG_PM_SLEEP) int acpi_dev_suspend_late(struct device *dev); int acpi_dev_resume_early(struct device *dev); int acpi_subsys_prepare(struct device *dev); @@ -526,9 +530,14 @@ static inline int acpi_subsys_resume_early(struct device *dev) { return 0; } #endif #if defined(CONFIG_ACPI) && defined(CONFIG_PM) +struct acpi_device *acpi_dev_pm_get_node(struct device *dev); int acpi_dev_pm_attach(struct device *dev, bool power_on); void acpi_dev_pm_detach(struct device *dev, bool power_off); #else +static inline struct acpi_device *acpi_dev_pm_get_node(struct device *dev) +{ + return NULL; +} static inline int acpi_dev_pm_attach(struct device *dev, bool power_on) { return -ENODEV; diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index a55b88eaf96a1708ea21cdf120ff87285e07ac8d..a22944ca05266ccb5761fc7e2fcf15fec2d8e2d6 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -89,11 +89,15 @@ struct cpufreq_real_policy { }; struct cpufreq_policy { - cpumask_var_t cpus; /* CPUs requiring sw coordination */ - cpumask_var_t related_cpus; /* CPUs with any coordination */ - unsigned int shared_type; /* ANY or ALL affected CPUs + /* CPUs sharing clock, require sw coordination */ + cpumask_var_t cpus; /* Online CPUs only */ + cpumask_var_t related_cpus; /* Online + Offline CPUs */ + + unsigned int shared_type; /* ACPI: ANY or ALL affected CPUs should set cpufreq */ - unsigned int cpu; /* cpu nr of registered CPU */ + unsigned int cpu; /* cpu nr of CPU managing this policy */ + unsigned int last_cpu; /* cpu nr of previous CPU that managed + * this policy */ struct cpufreq_cpuinfo cpuinfo;/* see above */ unsigned int min; /* in kHz */ @@ -112,16 +116,23 @@ struct cpufreq_policy { struct completion kobj_unregister; }; -#define CPUFREQ_ADJUST (0) -#define CPUFREQ_INCOMPATIBLE (1) -#define CPUFREQ_NOTIFY (2) -#define CPUFREQ_START (3) +#define CPUFREQ_ADJUST (0) +#define CPUFREQ_INCOMPATIBLE (1) +#define CPUFREQ_NOTIFY (2) +#define CPUFREQ_START (3) +#define CPUFREQ_UPDATE_POLICY_CPU (4) +/* Only for ACPI */ #define CPUFREQ_SHARED_TYPE_NONE (0) /* None */ #define CPUFREQ_SHARED_TYPE_HW (1) /* HW does needed coordination */ #define CPUFREQ_SHARED_TYPE_ALL (2) /* All dependent CPUs should set freq */ #define CPUFREQ_SHARED_TYPE_ANY (3) /* Freq can be set from any dependent CPU*/ +static inline bool policy_is_shared(struct cpufreq_policy *policy) +{ + return cpumask_weight(policy->cpus) > 1; +} + /******************** cpufreq transition notifiers *******************/ #define CPUFREQ_PRECHANGE (0) @@ -173,6 +184,7 @@ static inline unsigned long cpufreq_scale(unsigned long old, u_int div, u_int mu struct cpufreq_governor { char name[CPUFREQ_NAME_LEN]; + int initialized; int (*governor) (struct cpufreq_policy *policy, unsigned int event); ssize_t (*show_setspeed) (struct cpufreq_policy *policy, @@ -308,6 +320,9 @@ __ATTR(_name, 0444, show_##_name, NULL) static struct global_attr _name = \ __ATTR(_name, 0644, show_##_name, store_##_name) +struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu); +void cpufreq_cpu_put(struct cpufreq_policy *data); +const char *cpufreq_get_current_driver(void); /********************************************************************* * CPUFREQ 2.6. INTERFACE * @@ -397,14 +412,13 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy, /* the following 3 funtions are for cpufreq core use only */ struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu); -struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu); -void cpufreq_cpu_put(struct cpufreq_policy *data); /* the following are really really optional */ extern struct freq_attr cpufreq_freq_attr_scaling_available_freqs; void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table, unsigned int cpu); +void cpufreq_frequency_table_update_policy_cpu(struct cpufreq_policy *policy); void cpufreq_frequency_table_put_attr(unsigned int cpu); #endif /* _LINUX_CPUFREQ_H */ diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index 24cd1037b6d6f487d93ce79dfe0844887f949b9f..480c14dc1ddd5936d48820739ae6847c6e0c52bb 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -32,8 +32,6 @@ struct cpuidle_driver; ****************************/ struct cpuidle_state_usage { - void *driver_data; - unsigned long long disable; unsigned long long usage; unsigned long long time; /* in US */ @@ -62,26 +60,6 @@ struct cpuidle_state { #define CPUIDLE_DRIVER_FLAGS_MASK (0xFFFF0000) -/** - * cpuidle_get_statedata - retrieves private driver state data - * @st_usage: the state usage statistics - */ -static inline void *cpuidle_get_statedata(struct cpuidle_state_usage *st_usage) -{ - return st_usage->driver_data; -} - -/** - * cpuidle_set_statedata - stores private driver state data - * @st_usage: the state usage statistics - * @data: the private data - */ -static inline void -cpuidle_set_statedata(struct cpuidle_state_usage *st_usage, void *data) -{ - st_usage->driver_data = data; -} - struct cpuidle_device { unsigned int registered:1; unsigned int enabled:1; diff --git a/include/linux/freezer.h b/include/linux/freezer.h index e4238ceaa4d6a039d7acf55ae6ad69b6871ac4bd..e70df40d84f6fe83c72f732aa44b454148661b6e 100644 --- a/include/linux/freezer.h +++ b/include/linux/freezer.h @@ -12,6 +12,11 @@ extern atomic_t system_freezing_cnt; /* nr of freezing conds in effect */ extern bool pm_freezing; /* PM freezing in effect */ extern bool pm_nosig_freezing; /* PM nosig freezing in effect */ +/* + * Timeout for stopping processes + */ +extern unsigned int freeze_timeout_msecs; + /* * Check if a process has been frozen */ diff --git a/include/linux/mailbox.h b/include/linux/mailbox.h new file mode 100644 index 0000000000000000000000000000000000000000..5161f63ec1c875129debb7320d8d0782f0e48297 --- /dev/null +++ b/include/linux/mailbox.h @@ -0,0 +1,17 @@ +/* + * 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, see . + */ + +int pl320_ipc_transmit(u32 *data); +int pl320_ipc_register_notifier(struct notifier_block *nb); +int pl320_ipc_unregister_notifier(struct notifier_block *nb); diff --git a/include/linux/pm.h b/include/linux/pm.h index 03d7bb145311e5aca53beb6f078dbac218c434d8..97bcf23e045a2e4a15d0c0287ac1622d539a7d7f 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -31,7 +31,6 @@ /* * Callbacks for platform drivers to implement. */ -extern void (*pm_idle)(void); extern void (*pm_power_off)(void); extern void (*pm_power_off_prepare)(void); diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h index f271860c78d54ee4c794dcb6b7f432a9d7523a33..c785c215abfc54cb179d06aa81870178bc3b3255 100644 --- a/include/linux/pm_runtime.h +++ b/include/linux/pm_runtime.h @@ -80,6 +80,12 @@ static inline bool pm_runtime_suspended(struct device *dev) && !dev->power.disable_depth; } +static inline bool pm_runtime_active(struct device *dev) +{ + return dev->power.runtime_status == RPM_ACTIVE + || dev->power.disable_depth; +} + static inline bool pm_runtime_status_suspended(struct device *dev) { return dev->power.runtime_status == RPM_SUSPENDED; @@ -132,6 +138,7 @@ static inline void pm_runtime_put_noidle(struct device *dev) {} static inline bool device_run_wake(struct device *dev) { return false; } static inline void device_set_run_wake(struct device *dev, bool enable) {} static inline bool pm_runtime_suspended(struct device *dev) { return false; } +static inline bool pm_runtime_active(struct device *dev) { return true; } static inline bool pm_runtime_status_suspended(struct device *dev) { return false; } static inline bool pm_runtime_enabled(struct device *dev) { return false; } diff --git a/include/linux/suspend.h b/include/linux/suspend.h index 0c808d7fa579ec81d2da272caa0cc6630c9635a2..d4e3f16d5e8932c56e059d906add432cf88c8dbc 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h @@ -34,8 +34,10 @@ static inline void pm_restore_console(void) typedef int __bitwise suspend_state_t; #define PM_SUSPEND_ON ((__force suspend_state_t) 0) -#define PM_SUSPEND_STANDBY ((__force suspend_state_t) 1) +#define PM_SUSPEND_FREEZE ((__force suspend_state_t) 1) +#define PM_SUSPEND_STANDBY ((__force suspend_state_t) 2) #define PM_SUSPEND_MEM ((__force suspend_state_t) 3) +#define PM_SUSPEND_MIN PM_SUSPEND_FREEZE #define PM_SUSPEND_MAX ((__force suspend_state_t) 4) enum suspend_stat_step { @@ -192,6 +194,7 @@ struct platform_suspend_ops { */ extern void suspend_set_ops(const struct platform_suspend_ops *ops); extern int suspend_valid_only_mem(suspend_state_t state); +extern void freeze_wake(void); /** * arch_suspend_disable_irqs - disable IRQs for suspend @@ -217,6 +220,7 @@ extern int pm_suspend(suspend_state_t state); static inline void suspend_set_ops(const struct platform_suspend_ops *ops) {} static inline int pm_suspend(suspend_state_t state) { return -ENOSYS; } +static inline void freeze_wake(void) {} #endif /* !CONFIG_SUSPEND */ /* struct pbe is used for creating lists of pages that should be restored diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 381f06db2fe508bd660dd6c10c247aa5aedb5dda..e2cee22f578a6b24d7eb39c1ad298f15115bcb2d 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -181,6 +181,10 @@ int sysfs_merge_group(struct kobject *kobj, const struct attribute_group *grp); void sysfs_unmerge_group(struct kobject *kobj, const struct attribute_group *grp); +int sysfs_add_link_to_group(struct kobject *kobj, const char *group_name, + struct kobject *target, const char *link_name); +void sysfs_remove_link_from_group(struct kobject *kobj, const char *group_name, + const char *link_name); void sysfs_notify(struct kobject *kobj, const char *dir, const char *attr); void sysfs_notify_dirent(struct sysfs_dirent *sd); @@ -326,6 +330,18 @@ static inline void sysfs_unmerge_group(struct kobject *kobj, { } +static inline int sysfs_add_link_to_group(struct kobject *kobj, + const char *group_name, struct kobject *target, + const char *link_name) +{ + return 0; +} + +static inline void sysfs_remove_link_from_group(struct kobject *kobj, + const char *group_name, const char *link_name) +{ +} + static inline void sysfs_notify(struct kobject *kobj, const char *dir, const char *attr) { diff --git a/include/trace/events/power.h b/include/trace/events/power.h index 0c9783841a3033565fa90100d6c6efd003861267..427acab5d69af24899c4daf19b194e4abd67a243 100644 --- a/include/trace/events/power.h +++ b/include/trace/events/power.h @@ -99,98 +99,6 @@ DEFINE_EVENT(wakeup_source, wakeup_source_deactivate, TP_ARGS(name, state) ); -#ifdef CONFIG_EVENT_POWER_TRACING_DEPRECATED - -/* - * The power events are used for cpuidle & suspend (power_start, power_end) - * and for cpufreq (power_frequency) - */ -DECLARE_EVENT_CLASS(power, - - TP_PROTO(unsigned int type, unsigned int state, unsigned int cpu_id), - - TP_ARGS(type, state, cpu_id), - - TP_STRUCT__entry( - __field( u64, type ) - __field( u64, state ) - __field( u64, cpu_id ) - ), - - TP_fast_assign( - __entry->type = type; - __entry->state = state; - __entry->cpu_id = cpu_id; - ), - - TP_printk("type=%lu state=%lu cpu_id=%lu", (unsigned long)__entry->type, - (unsigned long)__entry->state, (unsigned long)__entry->cpu_id) -); - -DEFINE_EVENT(power, power_start, - - TP_PROTO(unsigned int type, unsigned int state, unsigned int cpu_id), - - TP_ARGS(type, state, cpu_id) -); - -DEFINE_EVENT(power, power_frequency, - - TP_PROTO(unsigned int type, unsigned int state, unsigned int cpu_id), - - TP_ARGS(type, state, cpu_id) -); - -TRACE_EVENT(power_end, - - TP_PROTO(unsigned int cpu_id), - - TP_ARGS(cpu_id), - - TP_STRUCT__entry( - __field( u64, cpu_id ) - ), - - TP_fast_assign( - __entry->cpu_id = cpu_id; - ), - - TP_printk("cpu_id=%lu", (unsigned long)__entry->cpu_id) - -); - -/* Deprecated dummy functions must be protected against multi-declartion */ -#ifndef _PWR_EVENT_AVOID_DOUBLE_DEFINING_DEPRECATED -#define _PWR_EVENT_AVOID_DOUBLE_DEFINING_DEPRECATED - -enum { - POWER_NONE = 0, - POWER_CSTATE = 1, - POWER_PSTATE = 2, -}; -#endif /* _PWR_EVENT_AVOID_DOUBLE_DEFINING_DEPRECATED */ - -#else /* CONFIG_EVENT_POWER_TRACING_DEPRECATED */ - -#ifndef _PWR_EVENT_AVOID_DOUBLE_DEFINING_DEPRECATED -#define _PWR_EVENT_AVOID_DOUBLE_DEFINING_DEPRECATED -enum { - POWER_NONE = 0, - POWER_CSTATE = 1, - POWER_PSTATE = 2, -}; - -/* These dummy declaration have to be ripped out when the deprecated - events get removed */ -static inline void trace_power_start(u64 type, u64 state, u64 cpuid) {}; -static inline void trace_power_end(u64 cpuid) {}; -static inline void trace_power_start_rcuidle(u64 type, u64 state, u64 cpuid) {}; -static inline void trace_power_end_rcuidle(u64 cpuid) {}; -static inline void trace_power_frequency(u64 type, u64 state, u64 cpuid) {}; -#endif /* _PWR_EVENT_AVOID_DOUBLE_DEFINING_DEPRECATED */ - -#endif /* CONFIG_EVENT_POWER_TRACING_DEPRECATED */ - /* * The clock events are used for clock enable/disable and for * clock rate change diff --git a/kernel/power/autosleep.c b/kernel/power/autosleep.c index ca304046d9e2b60c35c75eac43f5c3efcf2d0d01..c6422ffeda9a9c304a750b9321d555278b6a39d3 100644 --- a/kernel/power/autosleep.c +++ b/kernel/power/autosleep.c @@ -66,7 +66,7 @@ static DECLARE_WORK(suspend_work, try_to_suspend); void queue_up_suspend_work(void) { - if (!work_pending(&suspend_work) && autosleep_state > PM_SUSPEND_ON) + if (autosleep_state > PM_SUSPEND_ON) queue_work(autosleep_wq, &suspend_work); } diff --git a/kernel/power/main.c b/kernel/power/main.c index 1c16f9167de15c4151be06ad54be69a7ed8faeb6..d77663bfedeb071370f584f2bf1e42cd8332e5a4 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c @@ -313,7 +313,7 @@ static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr, static suspend_state_t decode_state(const char *buf, size_t n) { #ifdef CONFIG_SUSPEND - suspend_state_t state = PM_SUSPEND_STANDBY; + suspend_state_t state = PM_SUSPEND_MIN; const char * const *s; #endif char *p; @@ -553,6 +553,30 @@ power_attr(pm_trace_dev_match); #endif /* CONFIG_PM_TRACE */ +#ifdef CONFIG_FREEZER +static ssize_t pm_freeze_timeout_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "%u\n", freeze_timeout_msecs); +} + +static ssize_t pm_freeze_timeout_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t n) +{ + unsigned long val; + + if (kstrtoul(buf, 10, &val)) + return -EINVAL; + + freeze_timeout_msecs = val; + return n; +} + +power_attr(pm_freeze_timeout); + +#endif /* CONFIG_FREEZER*/ + static struct attribute * g[] = { &state_attr.attr, #ifdef CONFIG_PM_TRACE @@ -575,6 +599,9 @@ static struct attribute * g[] = { #ifdef CONFIG_PM_SLEEP_DEBUG &pm_print_times_attr.attr, #endif +#endif +#ifdef CONFIG_FREEZER + &pm_freeze_timeout_attr.attr, #endif NULL, }; diff --git a/kernel/power/process.c b/kernel/power/process.c index d5a258b60c6fd71aed065a0dd2ea5acadddc991f..98088e0e71e83a3b9cd157c5415f9e79083592c0 100644 --- a/kernel/power/process.c +++ b/kernel/power/process.c @@ -21,7 +21,7 @@ /* * Timeout for stopping processes */ -#define TIMEOUT (20 * HZ) +unsigned int __read_mostly freeze_timeout_msecs = 20 * MSEC_PER_SEC; static int try_to_freeze_tasks(bool user_only) { @@ -36,7 +36,7 @@ static int try_to_freeze_tasks(bool user_only) do_gettimeofday(&start); - end_time = jiffies + TIMEOUT; + end_time = jiffies + msecs_to_jiffies(freeze_timeout_msecs); if (!user_only) freeze_workqueues_begin(); diff --git a/kernel/power/qos.c b/kernel/power/qos.c index 9322ff7eaad68d41512763d3b337d123601f32b7..587dddeebf15610da6f93c35874381ea5156365a 100644 --- a/kernel/power/qos.c +++ b/kernel/power/qos.c @@ -359,8 +359,7 @@ void pm_qos_update_request(struct pm_qos_request *req, return; } - if (delayed_work_pending(&req->work)) - cancel_delayed_work_sync(&req->work); + cancel_delayed_work_sync(&req->work); if (new_value != req->node.prio) pm_qos_update_target( @@ -386,8 +385,7 @@ void pm_qos_update_request_timeout(struct pm_qos_request *req, s32 new_value, "%s called for unknown object.", __func__)) return; - if (delayed_work_pending(&req->work)) - cancel_delayed_work_sync(&req->work); + cancel_delayed_work_sync(&req->work); if (new_value != req->node.prio) pm_qos_update_target( @@ -416,8 +414,7 @@ void pm_qos_remove_request(struct pm_qos_request *req) return; } - if (delayed_work_pending(&req->work)) - cancel_delayed_work_sync(&req->work); + cancel_delayed_work_sync(&req->work); pm_qos_update_target(pm_qos_array[req->pm_qos_class]->constraints, &req->node, PM_QOS_REMOVE_REQ, diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index c8b7446b27dfc21add10f610e1692a2f3acee7ed..d4feda084a3aa9880611666352283deb1b28b3ef 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c @@ -30,12 +30,38 @@ #include "power.h" const char *const pm_states[PM_SUSPEND_MAX] = { + [PM_SUSPEND_FREEZE] = "freeze", [PM_SUSPEND_STANDBY] = "standby", [PM_SUSPEND_MEM] = "mem", }; static const struct platform_suspend_ops *suspend_ops; +static bool need_suspend_ops(suspend_state_t state) +{ + return !!(state > PM_SUSPEND_FREEZE); +} + +static DECLARE_WAIT_QUEUE_HEAD(suspend_freeze_wait_head); +static bool suspend_freeze_wake; + +static void freeze_begin(void) +{ + suspend_freeze_wake = false; +} + +static void freeze_enter(void) +{ + wait_event(suspend_freeze_wait_head, suspend_freeze_wake); +} + +void freeze_wake(void) +{ + suspend_freeze_wake = true; + wake_up(&suspend_freeze_wait_head); +} +EXPORT_SYMBOL_GPL(freeze_wake); + /** * suspend_set_ops - Set the global suspend method table. * @ops: Suspend operations to use. @@ -50,8 +76,11 @@ EXPORT_SYMBOL_GPL(suspend_set_ops); bool valid_state(suspend_state_t state) { + if (state == PM_SUSPEND_FREEZE) + return true; /* - * All states need lowlevel support and need to be valid to the lowlevel + * PM_SUSPEND_STANDBY and PM_SUSPEND_MEMORY states need lowlevel + * support and need to be valid to the lowlevel * implementation, no valid callback implies that none are valid. */ return suspend_ops && suspend_ops->valid && suspend_ops->valid(state); @@ -89,11 +118,11 @@ static int suspend_test(int level) * hibernation). Run suspend notifiers, allocate the "suspend" console and * freeze processes. */ -static int suspend_prepare(void) +static int suspend_prepare(suspend_state_t state) { int error; - if (!suspend_ops || !suspend_ops->enter) + if (need_suspend_ops(state) && (!suspend_ops || !suspend_ops->enter)) return -EPERM; pm_prepare_console(); @@ -137,7 +166,7 @@ static int suspend_enter(suspend_state_t state, bool *wakeup) { int error; - if (suspend_ops->prepare) { + if (need_suspend_ops(state) && suspend_ops->prepare) { error = suspend_ops->prepare(); if (error) goto Platform_finish; @@ -149,12 +178,23 @@ static int suspend_enter(suspend_state_t state, bool *wakeup) goto Platform_finish; } - if (suspend_ops->prepare_late) { + if (need_suspend_ops(state) && suspend_ops->prepare_late) { error = suspend_ops->prepare_late(); if (error) goto Platform_wake; } + /* + * PM_SUSPEND_FREEZE equals + * frozen processes + suspended devices + idle processors. + * Thus we should invoke freeze_enter() soon after + * all the devices are suspended. + */ + if (state == PM_SUSPEND_FREEZE) { + freeze_enter(); + goto Platform_wake; + } + if (suspend_test(TEST_PLATFORM)) goto Platform_wake; @@ -182,13 +222,13 @@ static int suspend_enter(suspend_state_t state, bool *wakeup) enable_nonboot_cpus(); Platform_wake: - if (suspend_ops->wake) + if (need_suspend_ops(state) && suspend_ops->wake) suspend_ops->wake(); dpm_resume_start(PMSG_RESUME); Platform_finish: - if (suspend_ops->finish) + if (need_suspend_ops(state) && suspend_ops->finish) suspend_ops->finish(); return error; @@ -203,11 +243,11 @@ int suspend_devices_and_enter(suspend_state_t state) int error; bool wakeup = false; - if (!suspend_ops) + if (need_suspend_ops(state) && !suspend_ops) return -ENOSYS; trace_machine_suspend(state); - if (suspend_ops->begin) { + if (need_suspend_ops(state) && suspend_ops->begin) { error = suspend_ops->begin(state); if (error) goto Close; @@ -226,7 +266,7 @@ int suspend_devices_and_enter(suspend_state_t state) do { error = suspend_enter(state, &wakeup); - } while (!error && !wakeup + } while (!error && !wakeup && need_suspend_ops(state) && suspend_ops->suspend_again && suspend_ops->suspend_again()); Resume_devices: @@ -236,13 +276,13 @@ int suspend_devices_and_enter(suspend_state_t state) ftrace_start(); resume_console(); Close: - if (suspend_ops->end) + if (need_suspend_ops(state) && suspend_ops->end) suspend_ops->end(); trace_machine_suspend(PWR_EVENT_EXIT); return error; Recover_platform: - if (suspend_ops->recover) + if (need_suspend_ops(state) && suspend_ops->recover) suspend_ops->recover(); goto Resume_devices; } @@ -278,12 +318,15 @@ static int enter_state(suspend_state_t state) if (!mutex_trylock(&pm_mutex)) return -EBUSY; + if (state == PM_SUSPEND_FREEZE) + freeze_begin(); + printk(KERN_INFO "PM: Syncing filesystems ... "); sys_sync(); printk("done.\n"); pr_debug("PM: Preparing system for %s sleep\n", pm_states[state]); - error = suspend_prepare(); + error = suspend_prepare(state); if (error) goto Unlock; diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig index 36567564e221195d1a8489207fed82f27c36b85e..192473b22799032c5cb013868f778ad4bc30626a 100644 --- a/kernel/trace/Kconfig +++ b/kernel/trace/Kconfig @@ -81,21 +81,6 @@ config EVENT_TRACING select CONTEXT_SWITCH_TRACER bool -config EVENT_POWER_TRACING_DEPRECATED - depends on EVENT_TRACING - bool "Deprecated power event trace API, to be removed" - default y - help - Provides old power event types: - C-state/idle accounting events: - power:power_start - power:power_end - and old cpufreq accounting event: - power:power_frequency - This is for userspace compatibility - and will vanish after 5 kernel iterations, - namely 3.1. - config CONTEXT_SWITCH_TRACER bool diff --git a/kernel/trace/power-traces.c b/kernel/trace/power-traces.c index f55fcf61b223d87e547568512ef2ae89e17107c5..1c71382b283d5abe23fedb1923952aa02ee6c73a 100644 --- a/kernel/trace/power-traces.c +++ b/kernel/trace/power-traces.c @@ -13,8 +13,5 @@ #define CREATE_TRACE_POINTS #include -#ifdef EVENT_POWER_TRACING_DEPRECATED -EXPORT_TRACEPOINT_SYMBOL_GPL(power_start); -#endif EXPORT_TRACEPOINT_SYMBOL_GPL(cpu_idle); diff --git a/tools/power/acpi/Makefile b/tools/power/acpi/Makefile index 6b9cf7a987c7c841664aebc21c072983e00053e1..bafeb8d662a3487bb17dae6d795d637de6de3313 100644 --- a/tools/power/acpi/Makefile +++ b/tools/power/acpi/Makefile @@ -13,6 +13,6 @@ clean : rm -f $(CLEANFILES) $(patsubst %.c,%.o, $(SRCS)) *~ install : - install acpidump /usr/bin/acpidump + install acpidump /usr/sbin/acpidump install acpidump.8 /usr/share/man/man8 diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8 index 0d7dc2cfefb57ebe1db21daa5e8ce84cba12a91f..b4ddb748356cdecda1a04a683dfe9d3917a42114 100644 --- a/tools/power/x86/turbostat/turbostat.8 +++ b/tools/power/x86/turbostat/turbostat.8 @@ -31,8 +31,6 @@ The \fB-S\fP option limits output to a 1-line System Summary for each interval. .PP The \fB-v\fP option increases verbosity. .PP -The \fB-s\fP option prints the SMI counter, equivalent to "-c 0x34" -.PP The \fB-c MSR#\fP option includes the delta of the specified 32-bit MSR counter. .PP The \fB-C MSR#\fP option includes the delta of the specified 64-bit MSR counter. @@ -186,26 +184,24 @@ This is a weighted average, where the weight is %c0. ie. it is the total number un-halted cycles elapsed per time divided by the number of CPUs. .SH SMI COUNTING EXAMPLE On Intel Nehalem and newer processors, MSR 0x34 is a System Management Mode Interrupt (SMI) counter. -Using the -m option, you can display how many SMIs have fired since reset, or if there -are SMIs during the measurement interval, you can display the delta using the -d option. +This counter is shown by default under the "SMI" column. .nf -[root@x980 ~]# turbostat -m 0x34 -cor CPU %c0 GHz TSC MSR 0x034 %c1 %c3 %c6 %pc3 %pc6 - 1.41 1.82 3.38 0x00000000 8.92 37.82 51.85 17.37 0.55 - 0 0 3.73 2.03 3.38 0x00000055 1.72 48.25 46.31 17.38 0.55 - 0 6 0.14 1.63 3.38 0x00000056 5.30 - 1 2 2.51 1.80 3.38 0x00000056 15.65 29.33 52.52 - 1 8 0.10 1.65 3.38 0x00000056 18.05 - 2 4 1.16 1.68 3.38 0x00000056 5.87 24.47 68.50 - 2 10 0.10 1.63 3.38 0x00000056 6.93 - 8 1 3.84 1.91 3.38 0x00000056 1.36 50.65 44.16 - 8 7 0.08 1.64 3.38 0x00000056 5.12 - 9 3 1.82 1.73 3.38 0x00000056 7.59 24.21 66.38 - 9 9 0.09 1.68 3.38 0x00000056 9.32 - 10 5 1.66 1.65 3.38 0x00000056 15.10 50.00 33.23 - 10 11 1.72 1.65 3.38 0x00000056 15.05 +[root@x980 ~]# turbostat +cor CPU %c0 GHz TSC SMI %c1 %c3 %c6 CTMP %pc3 %pc6 + 0.11 1.91 3.38 0 1.84 0.26 97.79 29 0.82 83.87 + 0 0 0.40 1.63 3.38 0 10.27 0.12 89.20 20 0.82 83.88 + 0 6 0.06 1.63 3.38 0 10.61 + 1 2 0.37 2.63 3.38 0 0.02 0.10 99.51 22 + 1 8 0.01 1.62 3.38 0 0.39 + 2 4 0.07 1.62 3.38 0 0.04 0.07 99.82 23 + 2 10 0.02 1.62 3.38 0 0.09 + 8 1 0.23 1.64 3.38 0 0.10 1.07 98.60 24 + 8 7 0.02 1.64 3.38 0 0.31 + 9 3 0.03 1.62 3.38 0 0.03 0.05 99.89 29 + 9 9 0.02 1.62 3.38 0 0.05 + 10 5 0.07 1.62 3.38 0 0.08 0.12 99.73 27 + 10 11 0.03 1.62 3.38 0 0.13 ^C -[root@x980 ~]# .fi .SH NOTES diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index ce6d46038f742d0b4fbc2d226abfbfe2401b00eb..6f3214ed4444ecb14c33cc29c3119057bf812cf5 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -58,6 +58,7 @@ unsigned int extra_msr_offset32; unsigned int extra_msr_offset64; unsigned int extra_delta_offset32; unsigned int extra_delta_offset64; +int do_smi; double bclk; unsigned int show_pkg; unsigned int show_core; @@ -99,6 +100,7 @@ struct thread_data { unsigned long long extra_delta64; unsigned long long extra_msr32; unsigned long long extra_delta32; + unsigned int smi_count; unsigned int cpu_id; unsigned int flags; #define CPU_IS_FIRST_THREAD_IN_CORE 0x2 @@ -248,6 +250,8 @@ void print_header(void) if (has_aperf) outp += sprintf(outp, " GHz"); outp += sprintf(outp, " TSC"); + if (do_smi) + outp += sprintf(outp, " SMI"); if (extra_delta_offset32) outp += sprintf(outp, " count 0x%03X", extra_delta_offset32); if (extra_delta_offset64) @@ -314,6 +318,8 @@ int dump_counters(struct thread_data *t, struct core_data *c, extra_msr_offset32, t->extra_msr32); fprintf(stderr, "msr0x%x: %016llX\n", extra_msr_offset64, t->extra_msr64); + if (do_smi) + fprintf(stderr, "SMI: %08X\n", t->smi_count); } if (c) { @@ -352,6 +358,7 @@ int dump_counters(struct thread_data *t, struct core_data *c, * RAM_W: %5.2 * GHz: "GHz" 3 columns %3.2 * TSC: "TSC" 3 columns %3.2 + * SMI: "SMI" 4 columns %4d * percentage " %pc3" %6.2 * Perf Status percentage: %5.2 * "CTMP" 4 columns %4d @@ -431,6 +438,10 @@ int format_counters(struct thread_data *t, struct core_data *c, /* TSC */ outp += sprintf(outp, "%5.2f", 1.0 * t->tsc/units/interval_float); + /* SMI */ + if (do_smi) + outp += sprintf(outp, "%4d", t->smi_count); + /* delta */ if (extra_delta_offset32) outp += sprintf(outp, " %11llu", t->extra_delta32); @@ -645,6 +656,9 @@ delta_thread(struct thread_data *new, struct thread_data *old, */ old->extra_msr32 = new->extra_msr32; old->extra_msr64 = new->extra_msr64; + + if (do_smi) + old->smi_count = new->smi_count - old->smi_count; } int delta_cpu(struct thread_data *t, struct core_data *c, @@ -672,6 +686,7 @@ void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data t->mperf = 0; t->c1 = 0; + t->smi_count = 0; t->extra_delta32 = 0; t->extra_delta64 = 0; @@ -802,6 +817,11 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p) return -4; } + if (do_smi) { + if (get_msr(cpu, MSR_SMI_COUNT, &msr)) + return -5; + t->smi_count = msr & 0xFFFFFFFF; + } if (extra_delta_offset32) { if (get_msr(cpu, extra_delta_offset32, &msr)) return -5; @@ -908,8 +928,7 @@ void print_verbose_header(void) get_msr(0, MSR_NHM_PLATFORM_INFO, &msr); - if (verbose) - fprintf(stderr, "cpu0: MSR_NHM_PLATFORM_INFO: 0x%08llx\n", msr); + fprintf(stderr, "cpu0: MSR_NHM_PLATFORM_INFO: 0x%08llx\n", msr); ratio = (msr >> 40) & 0xFF; fprintf(stderr, "%d * %.0f = %.0f MHz max efficiency\n", @@ -919,13 +938,16 @@ void print_verbose_header(void) fprintf(stderr, "%d * %.0f = %.0f MHz TSC frequency\n", ratio, bclk, ratio * bclk); + get_msr(0, MSR_IA32_POWER_CTL, &msr); + fprintf(stderr, "cpu0: MSR_IA32_POWER_CTL: 0x%08llx (C1E: %sabled)\n", + msr, msr & 0x2 ? "EN" : "DIS"); + if (!do_ivt_turbo_ratio_limit) goto print_nhm_turbo_ratio_limits; get_msr(0, MSR_IVT_TURBO_RATIO_LIMIT, &msr); - if (verbose) - fprintf(stderr, "cpu0: MSR_IVT_TURBO_RATIO_LIMIT: 0x%08llx\n", msr); + fprintf(stderr, "cpu0: MSR_IVT_TURBO_RATIO_LIMIT: 0x%08llx\n", msr); ratio = (msr >> 56) & 0xFF; if (ratio) @@ -1016,8 +1038,7 @@ void print_verbose_header(void) get_msr(0, MSR_NHM_TURBO_RATIO_LIMIT, &msr); - if (verbose) - fprintf(stderr, "cpu0: MSR_NHM_TURBO_RATIO_LIMIT: 0x%08llx\n", msr); + fprintf(stderr, "cpu0: MSR_NHM_TURBO_RATIO_LIMIT: 0x%08llx\n", msr); ratio = (msr >> 56) & 0xFF; if (ratio) @@ -1397,6 +1418,9 @@ int has_nehalem_turbo_ratio_limit(unsigned int family, unsigned int model) case 0x2D: /* SNB Xeon */ case 0x3A: /* IVB */ case 0x3E: /* IVB Xeon */ + case 0x3C: /* HSW */ + case 0x3F: /* HSW */ + case 0x45: /* HSW */ return 1; case 0x2E: /* Nehalem-EX Xeon - Beckton */ case 0x2F: /* Westmere-EX Xeon - Eagleton */ @@ -1488,6 +1512,9 @@ void rapl_probe(unsigned int family, unsigned int model) switch (model) { case 0x2A: case 0x3A: + case 0x3C: /* HSW */ + case 0x3F: /* HSW */ + case 0x45: /* HSW */ do_rapl = RAPL_PKG | RAPL_CORES | RAPL_GFX; break; case 0x2D: @@ -1724,6 +1751,9 @@ int is_snb(unsigned int family, unsigned int model) case 0x2D: case 0x3A: /* IVB */ case 0x3E: /* IVB Xeon */ + case 0x3C: /* HSW */ + case 0x3F: /* HSW */ + case 0x45: /* HSW */ return 1; } return 0; @@ -1883,6 +1913,7 @@ void check_cpuid() do_nehalem_platform_info = genuine_intel && has_invariant_tsc; do_nhm_cstates = genuine_intel; /* all Intel w/ non-stop TSC have NHM counters */ + do_smi = do_nhm_cstates; do_snb_cstates = is_snb(family, model); bclk = discover_bclk(family, model); @@ -2219,9 +2250,6 @@ void cmdline(int argc, char **argv) case 'c': sscanf(optarg, "%x", &extra_delta_offset32); break; - case 's': - extra_delta_offset32 = 0x34; /* SMI counter */ - break; case 'C': sscanf(optarg, "%x", &extra_delta_offset64); break; @@ -2248,7 +2276,7 @@ int main(int argc, char **argv) cmdline(argc, argv); if (verbose) - fprintf(stderr, "turbostat v3.0 November 23, 2012" + fprintf(stderr, "turbostat v3.2 February 11, 2013" " - Len Brown \n"); turbostat_init();