Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 39615
b: refs/heads/master
c: 786f18c
h: refs/heads/master
i:
  39613: 1be96ab
  39611: d174368
  39607: f1bfe13
  39599: 776ffd5
  39583: 28d64e8
  39551: f65257b
v: v3
  • Loading branch information
Dmitry Torokhov authored and Len Brown committed Oct 14, 2006
1 parent abb061d commit 0c530ba
Show file tree
Hide file tree
Showing 25 changed files with 998 additions and 1,081 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 18d508bf5144e645443e80c606ed513f77369a50
refs/heads/master: 786f18c666d7202a86a8aa42a98783b115fe8739
75 changes: 50 additions & 25 deletions trunk/Documentation/ibm-acpi.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,9 @@ detailed description):
- ACPI sounds
- temperature sensors
- Experimental: embedded controller register dump
- LCD brightness control
- Volume control
- Experimental: LCD brightness control
- Experimental: volume control
- Experimental: fan speed, fan enable/disable
- Experimental: WAN enable and disable

A compatibility table by model and feature is maintained on the web
site, http://ibm-acpi.sf.net/. I appreciate any success or failure
Expand All @@ -53,7 +52,40 @@ Installation

If you are compiling this driver as included in the Linux kernel
sources, simply enable the CONFIG_ACPI_IBM option (Power Management /
ACPI / IBM ThinkPad Laptop Extras).
ACPI / IBM ThinkPad Laptop Extras). The rest of this section describes
how to install this driver when downloaded from the web site.

First, you need to get a kernel with ACPI support up and running.
Please refer to http://acpi.sourceforge.net/ for help with this
step. How successful you will be depends a lot on you ThinkPad model,
the kernel you are using and any additional patches applied. The
kernel provided with your distribution may not be good enough. I
needed to compile a 2.6.7 kernel with the 20040715 ACPI patch to get
ACPI working reliably on my ThinkPad X40. Old ThinkPad models may not
be supported at all.

Assuming you have the basic ACPI support working (e.g. you can see the
/proc/acpi directory), follow the following steps to install this
driver:

- unpack the archive:

tar xzvf ibm-acpi-x.y.tar.gz; cd ibm-acpi-x.y

- compile the driver:

make

- install the module in your kernel modules directory:

make install

- load the module:

modprobe ibm_acpi

After loading the module, check the "dmesg" output for any error messages.


Features
--------
Expand Down Expand Up @@ -491,8 +523,13 @@ registers contain the current battery capacity, etc. If you experiment
with this, do send me your results (including some complete dumps with
a description of the conditions when they were taken.)

LCD brightness control -- /proc/acpi/ibm/brightness
---------------------------------------------------
EXPERIMENTAL: LCD brightness control -- /proc/acpi/ibm/brightness
-----------------------------------------------------------------

This feature is marked EXPERIMENTAL because the implementation
directly accesses hardware registers and may not work as expected. USE
WITH CAUTION! To use this feature, you need to supply the
experimental=1 parameter when loading the module.

This feature allows software control of the LCD brightness on ThinkPad
models which don't have a hardware brightness slider. The available
Expand All @@ -505,8 +542,13 @@ commands are:
The <level> number range is 0 to 7, although not all of them may be
distinct. The current brightness level is shown in the file.

Volume control -- /proc/acpi/ibm/volume
---------------------------------------
EXPERIMENTAL: Volume control -- /proc/acpi/ibm/volume
-----------------------------------------------------

This feature is marked EXPERIMENTAL because the implementation
directly accesses hardware registers and may not work as expected. USE
WITH CAUTION! To use this feature, you need to supply the
experimental=1 parameter when loading the module.

This feature allows volume control on ThinkPad models which don't have
a hardware volume knob. The available commands are:
Expand Down Expand Up @@ -569,23 +611,6 @@ with the following command:

echo 'level <level>' > /proc/acpi/ibm/thermal

EXPERIMENTAL: WAN -- /proc/acpi/ibm/wan
---------------------------------------

This feature is marked EXPERIMENTAL because the implementation
directly accesses hardware registers and may not work as expected. USE
WITH CAUTION! To use this feature, you need to supply the
experimental=1 parameter when loading the module.

This feature shows the presence and current state of a WAN (Sierra
Wireless EV-DO) device. If WAN is installed, the following commands can
be used:

echo enable > /proc/acpi/ibm/wan
echo disable > /proc/acpi/ibm/wan

It was tested on a Lenovo Thinkpad X60. It should probably work on other
Thinkpad models which come with this module installed.

Multiple Commands, Module Parameters
------------------------------------
Expand Down
7 changes: 0 additions & 7 deletions trunk/MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -1998,13 +1998,6 @@ M: rubini@ipvvis.unipv.it
L: linux-kernel@vger.kernel.org
S: Maintained

MSI LAPTOP SUPPORT
P: Lennart Poettering
M: mzxreary@0pointer.de
L: https://tango.0pointer.de/mailman/listinfo/s270-linux
W: http://0pointer.de/lennart/tchibo.html
S: Maintained

MTRR AND SIMILAR SUPPORT [i386]
P: Richard Gooch
M: rgooch@atnf.csiro.au
Expand Down
10 changes: 5 additions & 5 deletions trunk/arch/i386/kernel/acpi/boot.c
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ acpi_parse_ioapic(acpi_table_entry_header * header, const unsigned long end)
/*
* Parse Interrupt Source Override for the ACPI SCI
*/
static void acpi_sci_ioapic_setup(u32 bus_irq, u32 gsi, u16 polarity, u16 trigger)
static void acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger)
{
if (trigger == 0) /* compatible SCI trigger is level */
trigger = 3;
Expand All @@ -352,13 +352,13 @@ static void acpi_sci_ioapic_setup(u32 bus_irq, u32 gsi, u16 polarity, u16 trigge
* If GSI is < 16, this will update its flags,
* else it will create a new mp_irqs[] entry.
*/
mp_override_legacy_irq(bus_irq, polarity, trigger, gsi);
mp_override_legacy_irq(gsi, polarity, trigger, gsi);

/*
* stash over-ride to indicate we've been here
* and for later update of acpi_fadt
*/
acpi_sci_override_gsi = bus_irq;
acpi_sci_override_gsi = gsi;
return;
}

Expand All @@ -376,7 +376,7 @@ acpi_parse_int_src_ovr(acpi_table_entry_header * header,
acpi_table_print_madt_entry(header);

if (intsrc->bus_irq == acpi_fadt.sci_int) {
acpi_sci_ioapic_setup(intsrc->bus_irq, intsrc->global_irq,
acpi_sci_ioapic_setup(intsrc->global_irq,
intsrc->flags.polarity,
intsrc->flags.trigger);
return 0;
Expand Down Expand Up @@ -879,7 +879,7 @@ static int __init acpi_parse_madt_ioapic_entries(void)
* pretend we got one so we can set the SCI flags.
*/
if (!acpi_sci_override_gsi)
acpi_sci_ioapic_setup(acpi_fadt.sci_int, acpi_fadt.sci_int, 0, 0);
acpi_sci_ioapic_setup(acpi_fadt.sci_int, 0, 0);

/* Fill in identity legacy mapings where no override */
mp_config_acpi_legacy_irqs();
Expand Down
122 changes: 1 addition & 121 deletions trunk/arch/i386/kernel/acpi/cstate.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/acpi.h>
#include <linux/cpu.h>

#include <acpi/processor.h>
#include <asm/acpi.h>
Expand Down Expand Up @@ -42,124 +41,5 @@ void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags,
flags->bm_check = 1;
}
}
EXPORT_SYMBOL(acpi_processor_power_init_bm_check);

/* The code below handles cstate entry with monitor-mwait pair on Intel*/

struct cstate_entry_s {
struct {
unsigned int eax;
unsigned int ecx;
} states[ACPI_PROCESSOR_MAX_POWER];
};
static struct cstate_entry_s *cpu_cstate_entry; /* per CPU ptr */

static short mwait_supported[ACPI_PROCESSOR_MAX_POWER];

#define MWAIT_SUBSTATE_MASK (0xf)
#define MWAIT_SUBSTATE_SIZE (4)

#define CPUID_MWAIT_LEAF (5)
#define CPUID5_ECX_EXTENSIONS_SUPPORTED (0x1)
#define CPUID5_ECX_INTERRUPT_BREAK (0x2)

#define MWAIT_ECX_INTERRUPT_BREAK (0x1)

#define NATIVE_CSTATE_BEYOND_HALT (2)

int acpi_processor_ffh_cstate_probe(unsigned int cpu,
struct acpi_processor_cx *cx, struct acpi_power_register *reg)
{
struct cstate_entry_s *percpu_entry;
struct cpuinfo_x86 *c = cpu_data + cpu;

cpumask_t saved_mask;
int retval;
unsigned int eax, ebx, ecx, edx;
unsigned int edx_part;
unsigned int cstate_type; /* C-state type and not ACPI C-state type */
unsigned int num_cstate_subtype;

if (!cpu_cstate_entry || c->cpuid_level < CPUID_MWAIT_LEAF )
return -1;

if (reg->bit_offset != NATIVE_CSTATE_BEYOND_HALT)
return -1;

percpu_entry = per_cpu_ptr(cpu_cstate_entry, cpu);
percpu_entry->states[cx->index].eax = 0;
percpu_entry->states[cx->index].ecx = 0;

/* Make sure we are running on right CPU */
saved_mask = current->cpus_allowed;
retval = set_cpus_allowed(current, cpumask_of_cpu(cpu));
if (retval)
return -1;

cpuid(CPUID_MWAIT_LEAF, &eax, &ebx, &ecx, &edx);

/* Check whether this particular cx_type (in CST) is supported or not */
cstate_type = (cx->address >> MWAIT_SUBSTATE_SIZE) + 1;
edx_part = edx >> (cstate_type * MWAIT_SUBSTATE_SIZE);
num_cstate_subtype = edx_part & MWAIT_SUBSTATE_MASK;

retval = 0;
if (num_cstate_subtype < (cx->address & MWAIT_SUBSTATE_MASK)) {
retval = -1;
goto out;
}

/* mwait ecx extensions INTERRUPT_BREAK should be supported for C2/C3 */
if (!(ecx & CPUID5_ECX_EXTENSIONS_SUPPORTED) ||
!(ecx & CPUID5_ECX_INTERRUPT_BREAK)) {
retval = -1;
goto out;
}
percpu_entry->states[cx->index].ecx = MWAIT_ECX_INTERRUPT_BREAK;

/* Use the hint in CST */
percpu_entry->states[cx->index].eax = cx->address;

if (!mwait_supported[cstate_type]) {
mwait_supported[cstate_type] = 1;
printk(KERN_DEBUG "Monitor-Mwait will be used to enter C-%d "
"state\n", cx->type);
}

out:
set_cpus_allowed(current, saved_mask);
return retval;
}
EXPORT_SYMBOL_GPL(acpi_processor_ffh_cstate_probe);

void acpi_processor_ffh_cstate_enter(struct acpi_processor_cx *cx)
{
unsigned int cpu = smp_processor_id();
struct cstate_entry_s *percpu_entry;

percpu_entry = per_cpu_ptr(cpu_cstate_entry, cpu);
mwait_idle_with_hints(percpu_entry->states[cx->index].eax,
percpu_entry->states[cx->index].ecx);
}
EXPORT_SYMBOL_GPL(acpi_processor_ffh_cstate_enter);

static int __init ffh_cstate_init(void)
{
struct cpuinfo_x86 *c = &boot_cpu_data;
if (c->x86_vendor != X86_VENDOR_INTEL)
return -1;

cpu_cstate_entry = alloc_percpu(struct cstate_entry_s);
return 0;
}

static void __exit ffh_cstate_exit(void)
{
if (cpu_cstate_entry) {
free_percpu(cpu_cstate_entry);
cpu_cstate_entry = NULL;
}
}

arch_initcall(ffh_cstate_init);
__exitcall(ffh_cstate_exit);
EXPORT_SYMBOL(acpi_processor_power_init_bm_check);
22 changes: 7 additions & 15 deletions trunk/arch/i386/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -236,28 +236,20 @@ EXPORT_SYMBOL_GPL(cpu_idle_wait);
* We execute MONITOR against need_resched and enter optimized wait state
* through MWAIT. Whenever someone changes need_resched, we would be woken
* up from MWAIT (without an IPI).
*
* New with Core Duo processors, MWAIT can take some hints based on CPU
* capability.
*/
void mwait_idle_with_hints(unsigned long eax, unsigned long ecx)
static void mwait_idle(void)
{
if (!need_resched()) {
local_irq_enable();

while (!need_resched()) {
__monitor((void *)&current_thread_info()->flags, 0, 0);
smp_mb();
if (!need_resched())
__mwait(eax, ecx);
if (need_resched())
break;
__mwait(0, 0);
}
}

/* Default MONITOR/MWAIT with no hints, used for default C1 state */
static void mwait_idle(void)
{
local_irq_enable();
while (!need_resched())
mwait_idle_with_hints(0, 0);
}

void __devinit select_idle_routine(const struct cpuinfo_x86 *c)
{
if (cpu_has(c, X86_FEATURE_MWAIT)) {
Expand Down
22 changes: 7 additions & 15 deletions trunk/arch/x86_64/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -238,28 +238,20 @@ void cpu_idle (void)
* We execute MONITOR against need_resched and enter optimized wait state
* through MWAIT. Whenever someone changes need_resched, we would be woken
* up from MWAIT (without an IPI).
*
* New with Core Duo processors, MWAIT can take some hints based on CPU
* capability.
*/
void mwait_idle_with_hints(unsigned long eax, unsigned long ecx)
static void mwait_idle(void)
{
if (!need_resched()) {
local_irq_enable();

while (!need_resched()) {
__monitor((void *)&current_thread_info()->flags, 0, 0);
smp_mb();
if (!need_resched())
__mwait(eax, ecx);
if (need_resched())
break;
__mwait(0, 0);
}
}

/* Default MONITOR/MWAIT with no hints, used for default C1 state */
static void mwait_idle(void)
{
local_irq_enable();
while (!need_resched())
mwait_idle_with_hints(0,0);
}

void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
{
static int printed;
Expand Down
Loading

0 comments on commit 0c530ba

Please sign in to comment.