~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to arch/x86/kernel/acpi/cstate.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2005 Intel Corporation
 
3
 *      Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
 
4
 *      - Added _PDC for SMP C-states on Intel CPUs
 
5
 */
 
6
 
 
7
#include <linux/kernel.h>
 
8
#include <linux/module.h>
 
9
#include <linux/init.h>
 
10
#include <linux/acpi.h>
 
11
#include <linux/cpu.h>
 
12
#include <linux/sched.h>
 
13
 
 
14
#include <acpi/processor.h>
 
15
#include <asm/acpi.h>
 
16
#include <asm/mwait.h>
 
17
 
 
18
/*
 
19
 * Initialize bm_flags based on the CPU cache properties
 
20
 * On SMP it depends on cache configuration
 
21
 * - When cache is not shared among all CPUs, we flush cache
 
22
 *   before entering C3.
 
23
 * - When cache is shared among all CPUs, we use bm_check
 
24
 *   mechanism as in UP case
 
25
 *
 
26
 * This routine is called only after all the CPUs are online
 
27
 */
 
28
void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags,
 
29
                                        unsigned int cpu)
 
30
{
 
31
        struct cpuinfo_x86 *c = &cpu_data(cpu);
 
32
 
 
33
        flags->bm_check = 0;
 
34
        if (num_online_cpus() == 1)
 
35
                flags->bm_check = 1;
 
36
        else if (c->x86_vendor == X86_VENDOR_INTEL) {
 
37
                /*
 
38
                 * Today all MP CPUs that support C3 share cache.
 
39
                 * And caches should not be flushed by software while
 
40
                 * entering C3 type state.
 
41
                 */
 
42
                flags->bm_check = 1;
 
43
        }
 
44
 
 
45
        /*
 
46
         * On all recent Intel platforms, ARB_DISABLE is a nop.
 
47
         * So, set bm_control to zero to indicate that ARB_DISABLE
 
48
         * is not required while entering C3 type state on
 
49
         * P4, Core and beyond CPUs
 
50
         */
 
51
        if (c->x86_vendor == X86_VENDOR_INTEL &&
 
52
            (c->x86 > 0xf || (c->x86 == 6 && c->x86_model >= 0x0f)))
 
53
                        flags->bm_control = 0;
 
54
}
 
55
EXPORT_SYMBOL(acpi_processor_power_init_bm_check);
 
56
 
 
57
/* The code below handles cstate entry with monitor-mwait pair on Intel*/
 
58
 
 
59
struct cstate_entry {
 
60
        struct {
 
61
                unsigned int eax;
 
62
                unsigned int ecx;
 
63
        } states[ACPI_PROCESSOR_MAX_POWER];
 
64
};
 
65
static struct cstate_entry __percpu *cpu_cstate_entry;  /* per CPU ptr */
 
66
 
 
67
static short mwait_supported[ACPI_PROCESSOR_MAX_POWER];
 
68
 
 
69
#define NATIVE_CSTATE_BEYOND_HALT       (2)
 
70
 
 
71
static long acpi_processor_ffh_cstate_probe_cpu(void *_cx)
 
72
{
 
73
        struct acpi_processor_cx *cx = _cx;
 
74
        long retval;
 
75
        unsigned int eax, ebx, ecx, edx;
 
76
        unsigned int edx_part;
 
77
        unsigned int cstate_type; /* C-state type and not ACPI C-state type */
 
78
        unsigned int num_cstate_subtype;
 
79
 
 
80
        cpuid(CPUID_MWAIT_LEAF, &eax, &ebx, &ecx, &edx);
 
81
 
 
82
        /* Check whether this particular cx_type (in CST) is supported or not */
 
83
        cstate_type = ((cx->address >> MWAIT_SUBSTATE_SIZE) &
 
84
                        MWAIT_CSTATE_MASK) + 1;
 
85
        edx_part = edx >> (cstate_type * MWAIT_SUBSTATE_SIZE);
 
86
        num_cstate_subtype = edx_part & MWAIT_SUBSTATE_MASK;
 
87
 
 
88
        retval = 0;
 
89
        if (num_cstate_subtype < (cx->address & MWAIT_SUBSTATE_MASK)) {
 
90
                retval = -1;
 
91
                goto out;
 
92
        }
 
93
 
 
94
        /* mwait ecx extensions INTERRUPT_BREAK should be supported for C2/C3 */
 
95
        if (!(ecx & CPUID5_ECX_EXTENSIONS_SUPPORTED) ||
 
96
            !(ecx & CPUID5_ECX_INTERRUPT_BREAK)) {
 
97
                retval = -1;
 
98
                goto out;
 
99
        }
 
100
 
 
101
        if (!mwait_supported[cstate_type]) {
 
102
                mwait_supported[cstate_type] = 1;
 
103
                printk(KERN_DEBUG
 
104
                        "Monitor-Mwait will be used to enter C-%d "
 
105
                        "state\n", cx->type);
 
106
        }
 
107
        snprintf(cx->desc,
 
108
                        ACPI_CX_DESC_LEN, "ACPI FFH INTEL MWAIT 0x%x",
 
109
                        cx->address);
 
110
out:
 
111
        return retval;
 
112
}
 
113
 
 
114
int acpi_processor_ffh_cstate_probe(unsigned int cpu,
 
115
                struct acpi_processor_cx *cx, struct acpi_power_register *reg)
 
116
{
 
117
        struct cstate_entry *percpu_entry;
 
118
        struct cpuinfo_x86 *c = &cpu_data(cpu);
 
119
        long retval;
 
120
 
 
121
        if (!cpu_cstate_entry || c->cpuid_level < CPUID_MWAIT_LEAF)
 
122
                return -1;
 
123
 
 
124
        if (reg->bit_offset != NATIVE_CSTATE_BEYOND_HALT)
 
125
                return -1;
 
126
 
 
127
        percpu_entry = per_cpu_ptr(cpu_cstate_entry, cpu);
 
128
        percpu_entry->states[cx->index].eax = 0;
 
129
        percpu_entry->states[cx->index].ecx = 0;
 
130
 
 
131
        /* Make sure we are running on right CPU */
 
132
 
 
133
        retval = work_on_cpu(cpu, acpi_processor_ffh_cstate_probe_cpu, cx);
 
134
        if (retval == 0) {
 
135
                /* Use the hint in CST */
 
136
                percpu_entry->states[cx->index].eax = cx->address;
 
137
                percpu_entry->states[cx->index].ecx = MWAIT_ECX_INTERRUPT_BREAK;
 
138
        }
 
139
 
 
140
        /*
 
141
         * For _CST FFH on Intel, if GAS.access_size bit 1 is cleared,
 
142
         * then we should skip checking BM_STS for this C-state.
 
143
         * ref: "Intel Processor Vendor-Specific ACPI Interface Specification"
 
144
         */
 
145
        if ((c->x86_vendor == X86_VENDOR_INTEL) && !(reg->access_size & 0x2))
 
146
                cx->bm_sts_skip = 1;
 
147
 
 
148
        return retval;
 
149
}
 
150
EXPORT_SYMBOL_GPL(acpi_processor_ffh_cstate_probe);
 
151
 
 
152
/*
 
153
 * This uses new MONITOR/MWAIT instructions on P4 processors with PNI,
 
154
 * which can obviate IPI to trigger checking of need_resched.
 
155
 * We execute MONITOR against need_resched and enter optimized wait state
 
156
 * through MWAIT. Whenever someone changes need_resched, we would be woken
 
157
 * up from MWAIT (without an IPI).
 
158
 *
 
159
 * New with Core Duo processors, MWAIT can take some hints based on CPU
 
160
 * capability.
 
161
 */
 
162
void mwait_idle_with_hints(unsigned long ax, unsigned long cx)
 
163
{
 
164
        if (!need_resched()) {
 
165
                if (this_cpu_has(X86_FEATURE_CLFLUSH_MONITOR))
 
166
                        clflush((void *)&current_thread_info()->flags);
 
167
 
 
168
                __monitor((void *)&current_thread_info()->flags, 0, 0);
 
169
                smp_mb();
 
170
                if (!need_resched())
 
171
                        __mwait(ax, cx);
 
172
        }
 
173
}
 
174
 
 
175
void acpi_processor_ffh_cstate_enter(struct acpi_processor_cx *cx)
 
176
{
 
177
        unsigned int cpu = smp_processor_id();
 
178
        struct cstate_entry *percpu_entry;
 
179
 
 
180
        percpu_entry = per_cpu_ptr(cpu_cstate_entry, cpu);
 
181
        mwait_idle_with_hints(percpu_entry->states[cx->index].eax,
 
182
                              percpu_entry->states[cx->index].ecx);
 
183
}
 
184
EXPORT_SYMBOL_GPL(acpi_processor_ffh_cstate_enter);
 
185
 
 
186
static int __init ffh_cstate_init(void)
 
187
{
 
188
        struct cpuinfo_x86 *c = &boot_cpu_data;
 
189
        if (c->x86_vendor != X86_VENDOR_INTEL)
 
190
                return -1;
 
191
 
 
192
        cpu_cstate_entry = alloc_percpu(struct cstate_entry);
 
193
        return 0;
 
194
}
 
195
 
 
196
static void __exit ffh_cstate_exit(void)
 
197
{
 
198
        free_percpu(cpu_cstate_entry);
 
199
        cpu_cstate_entry = NULL;
 
200
}
 
201
 
 
202
arch_initcall(ffh_cstate_init);
 
203
__exitcall(ffh_cstate_exit);